Обычная версия
Java форум JavaTalks
форум программистов

Поиск   Пользователи   Группы   Регистрация 
 Профиль   Личные сообщения 

 Вход 

Вложенные таблицы (JPA Hibernate)
Список форумов
 ->  Персистентность в Java (JPA, ORM, ODB)


На страницу 1, 2  След. 
Начать новую тему 
Предыдущая тема :: Следующая тема  
Автор Сообщение
Z___ZZZ : 13
Новичок

СообщениеДек 29, 2011 11:55 
Ответить с цитатой
Во-первых, Здравствуйте!
Во-вторых, я новичок!
В-третьих, проблема!

Есть две сущности Person и Address. Необходимо, чтобы сущность Address была вложенной. У меня в таблице address есть foreighn key -personId, который ссылается на primary key (id) таблицы person. В сущностях прописываю связи OneToOne, однако при добавлении записи Person+Address никоим образом не генерируется personId (т.е. оно нулевое), а так как у меня personId not null hibernate выдает ошибку, что couldn not insert

Код
Person
Код:

@Entity
@Table(name = "person")
@NamedQueries({
    @NamedQuery(name = "Person.findAll", query = "SELECT p FROM Person p")})
public class Person implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @NotNull
    @Column(name = "id")
    private Integer id;
    @Basic(optional = false)
    @NotNull
    @Size(min = 1, max = 500)
    @Column(name = "firstName")
    private String firstName;
    @Basic(optional = false)
    @NotNull
    @Size(min = 1, max = 500)
    @Column(name = "lastName")
    private String lastName;
    @Column(name = "dob")
    @Temporal(TemporalType.DATE)
    private Date dob;
    @OneToOne(cascade = CascadeType.ALL, mappedBy = "personId")
    private Address address;

    public Person() {
    }

    public Address getAddress() {
        return address;
    }
............
}



Address
Код:

@Entity
@Table(name = "address")
@NamedQueries({
    @NamedQuery(name = "Address.findAll", query = "SELECT a FROM Address a")})
public class Address implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @NotNull
    @Column(name = "id")
    private Integer id;
    @Basic(optional = false)
    @NotNull
    @Size(min = 1, max = 255)
    @Column(name = "city")
    private String city;
    @Basic(optional = false)
    @NotNull
    @Size(min = 1, max = 500)
    @Column(name = "firstString")
    private String firstString;
    @Size(max = 500)
    @Column(name = "secondString")
    private String secondString;
    @JoinColumn(name = "personId", referencedColumnName = "id", nullable=false)
    @OneToOne(optional = false, cascade= CascadeType.ALL)
    private Person personId;
  public Person getPersonId() {
        return personId;
    }

    public void setPersonId(Person personId) {
        this.personId = personId;
    }
........................
}


А это я создаю таблицу

Код:
CREATE TABLE Address(
 id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
 personId INT NOT NULL,
 city VARCHAR(255) NOT NULL,
 firstString VARCHAR(500) NOT NULL,
 secondString VARCHAR(500),
 FOREIGN KEY (personId) REFERENCES Person(id)
);


подскажите что-нибудь. У меня personId должен заполняться автоматически, в него должно записываться значение id из Person. Может я не туда забрел вообще?id
Код:
К началу Посмотреть профиль Отправить личное сообщение
Mam(O)n : 61
Новичок

СообщениеДек 29, 2011 12:25 
Ответить с цитатой
Ну во-первых, а что, если снять @NotNull с поля id?
Ну и во-вторых, если нужна просто вложенная сущность, то может можно обойтись @Embedded/@Embeddable?
К началу Посмотреть профиль Отправить личное сообщение
Z___ZZZ : 13
Новичок

СообщениеДек 29, 2011 13:00 
Ответить с цитатой
Mam(O)n писал(а):
Ну во-первых, а что, если снять @NotNull с поля id?
Ну и во-вторых, если нужна просто вложенная сущность, то может можно обойтись @Embedded/@Embeddable?

1.снимать not null нельзя - ибо мой personId - это как бы ссылка на запись в таблице person, т.е. она должна заполняться автоматом.
2. условия такие
К началу Посмотреть профиль Отправить личное сообщение
Mam(O)n : 61
Новичок

СообщениеДек 29, 2011 13:10 
Ответить с цитатой
Ну тут такая тема, что автоматическое значение оно как бы генерируется в момент записи в таблицу, на уровне СУБД, а валидация бинов происходит раньше передачи данных в СУБД, отсюда и срабатывание @NotNull.

И наверное мне стоит уточнить, что аннотация @NotNull отношения к NOT NULL в СУБД не имеет. Эта аннотация относится к JSR 303 Bean Validation.
К началу Посмотреть профиль Отправить личное сообщение
Z___ZZZ : 13
Новичок

СообщениеДек 29, 2011 14:11 
Ответить с цитатой
объявил поле personId так , что оно может принимать нулевые значения. в итоге в БД все personId NULL.
К началу Посмотреть профиль Отправить личное сообщение
Z___ZZZ : 13
Новичок

СообщениеДек 29, 2011 16:58 
Ответить с цитатой
Суть такая - надо на форме вводит объект класса Person с дополнительными атрибутами. Доп атрибуты - это объект класса Address. Соответственно, удаляя объект Person - удаляется ссылочный объект Address
К началу Посмотреть профиль Отправить личное сообщение
Mam(O)n : 61
Новичок

СообщениеДек 29, 2011 17:02 
Ответить с цитатой
Я имел ввиду @NotNull не на personId снять, а на id надо снять. Ну да и ладно, первая проблема я как вижу решилась. Теперь вторую проблему надо исправить, приведя аннотации отношений к следующему виду:

Код:
    @NotNull
    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn (name = "addressId", referencedColumnName = "id")
    private Address address;

Код:
    @NotNull
    @OneToOne (cascade= CascadeType.ALL)
    @JoinColumn (name = "personId", referencedColumnName = "id")
    private Person person;
К началу Посмотреть профиль Отправить личное сообщение
Z___ZZZ : 13
Новичок

СообщениеДек 29, 2011 17:27 
Ответить с цитатой
Mam(O)n писал(а):
Я имел ввиду @NotNull не на personId снять, а на id надо снять. Ну да и ладно, первая проблема я как вижу решилась. Теперь вторую проблему надо исправить, приведя аннотации отношений к следующему виду:

Код:
    @NotNull
    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn (name = "addressId", referencedColumnName = "id")
    private Address address;

Код:
    @NotNull
    @OneToOne (cascade= CascadeType.ALL)
    @JoinColumn (name = "personId", referencedColumnName = "id")
    private Person person;


ок. допустим так я сделал. какие мои дальнейшие действия.

и еще - в вашем коде мне необходимо еще задавать foreighn key addressId в таблице person который будет ссылаться на Address. это я сделаю, но можно было это опустить как я понимаю.
К началу Посмотреть профиль Отправить личное сообщение
Mam(O)n : 61
Новичок

СообщениеДек 29, 2011 17:49 
Ответить с цитатой
Z___ZZZ писал(а):
ок. допустим так я сделал. какие мои дальнейшие действия.

Ну допустим можно использовать эти сущности в CRUD операциях так:
Код:

@Stateless
@Path ("person")
public class PersonBean
{
   @PersistenceContext (unitName = "example")
   private EntityManager entityManager;
   
   @GET
   @Path ("{id}")
   @Produces (MediaType.APPLICATION_JSON)
   public Person get (@PathParam("id") Integer id)
   {
      return entityManager.find(Person.class, id);
   }
   
   @PUT
   public void put (   @FormParam("firstName") String firstName,
                  @FormParam("lastName") String lastName,
                  @FormParam("city") String city,
                  @FormParam("firstString") String firstString,
                  @FormParam("secondString") String secondString)
   {
      Person person = new Person();
      Address address = new Address();
      person.setAddress(address);
      person.setFirstName(firstName);
      person.setLastName(lastName);
      address.setCity(city);
      address.setFirstString(firstString);
      address.setSecondString(secondString);
      entityManager.persist(person);
   }
   
   @DELETE
   @Path ("{id}")
   public void delete (@PathParam("id") Integer id)
   {
      entityManager.remove(entityManager.find(Person.class, id));
   }
}


Z___ZZZ писал(а):

и еще - в вашем коде мне необходимо еще задавать foreighn key addressId в таблице person который будет ссылаться на Address. это я сделаю, но можно было это опустить как я понимаю.
Совершенно верное замечание. Особого смысла держать обратную ссылку я не вижу смысла в контексте отношений данных сущностей, и поле personId из сущности Address можно изъять.[/code][/quote]
К началу Посмотреть профиль Отправить личное сообщение
Z___ZZZ : 13
Новичок

СообщениеДек 29, 2011 17:57 
Ответить с цитатой
все понял.

да вот в чем проблема то. у меня контроллер уже реализован, все GRUD реализованы. по сабмиту в бд записывается как Person так и Address. проблема именно в том чтобы эти две таблицы как то были связаны, чтобы удалив запись из Person, удалилась соответствующая ему запись из Address. в этом вся загвоздка((
К началу Посмотреть профиль Отправить личное сообщение
Mam(O)n : 61
Новичок

СообщениеДек 29, 2011 18:07 
Ответить с цитатой
Я данную связку сущностей у себя на Glassfish-3.1.1 (ORM - EclipseLink) запустил, и при entityManager.remove(person) у меня также из базы средствами ORM и связная запись address вычищается. Если что, сущности у меня так выглядят:

Код:

package com.example.entities;

import javax.persistence.*;
import javax.validation.constraints.*;
import lombok.*;

@Entity
public class Person
{
    @Id
    @Getter @Setter
    @GeneratedValue (strategy = GenerationType.IDENTITY)
    private Integer id;
   
    @NotNull
    @Getter @Setter
    @Size (min = 1, max = 500)
    @Column (nullable = false)
    private String firstName;
   
    @NotNull
    @Getter @Setter
    @Size (min = 1, max = 500)
    @Column (name = "lastName")
    private String lastName;
   
    @Getter @Setter
    @Temporal (TemporalType.DATE)
    private java.util.Date dob;
   
    @NotNull
    @Getter @Setter
    @OneToOne(cascade = CascadeType.ALL)
    private Address address;
}

Код:

package com.example.entities;

import javax.persistence.*;
import javax.validation.constraints.*;
import lombok.*;

@Entity
public class Address
{
    @Id
    @Getter @Setter
    @GeneratedValue (strategy = GenerationType.IDENTITY)
    private Integer id;
   
    @NotNull
    @Getter @Setter
    @Size (min = 1, max = 255)
    @Column (nullable = false)
    private String city;
   
    @NotNull
    @Getter @Setter
    @Size (min = 1, max = 500)
    @Column (nullable = false)
    private String firstString;
   
    @Getter @Setter
    @Size (max = 500)
    private String secondString;
}
К началу Посмотреть профиль Отправить личное сообщение
Z___ZZZ : 13
Новичок

СообщениеДек 30, 2011 10:19 
Ответить с цитатой
короче ничего не получается. все перепробовал, что тут описали.

снимок БД

может я в DAO классе что нитак сделал?

Код:
package com.mycompany.person;

import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

/**
 *
 * @author TROFIMOVEA
 */
@Repository
public class AddressDAOImpl implements AddressDAO{

   
    @Autowired
    private SessionFactory sessionFactory;
   
     @Override
    public void addAddress(Address address) {
         
        sessionFactory.getCurrentSession().save(address);
    }

    /* @Override
    public void deleteAddress(Integer id) {
        Address address = (Address) sessionFactory.getCurrentSession().load(
                Address.class, id);
        if (null != address) {
            sessionFactory.getCurrentSession().delete(address);
    }*/
}
К началу Посмотреть профиль Отправить личное сообщение
Mam(O)n : 61
Новичок

СообщениеДек 30, 2011 11:39 
Ответить с цитатой
Ну в общем то правильнее будет манипулировать на уровне orm только одной сущностью, например Person, а сущность Address, которая должна быть указана внутри сущности Person, уже по указанному CascadeType.ALL автоматически и сохраняться и удаляться будет вместе с сущностью Person. Вот например, в мной приведённом коде restful сессионного бина создаётся два pojo Person и Address, затем присваивается person.setAddress(address) и делается один entityManger.persist(person), который убивает два зайца - сохраняет сущность и Person и Address. Также и удаление происходит вытягиванием только сущности Person.

И да, SessionFactory, это hibernate-specific и выходит за рамки JPA. Тут я не могу подсказать, может у него и поведение другое.
К началу Посмотреть профиль Отправить личное сообщение
sgdread : 2184
JT Библиотекарь
Откуда: USA

СообщениеДек 30, 2011 11:55 
Ответить с цитатой
Mam(O)n писал(а):
CascadeType.ALL автоматически и сохраняться и удаляться будет вместе с сущностью Person.

Есть нюансы. К примеру в Hibernate на коллекциях сиротки не удаляются. Нужно ставить свойство orphanRemoval:
Код:
@OneToMany(mappedBy=”foo”, orphanRemoval=true)

Mam(O)n писал(а):
И да, SessionFactory, это hibernate-specific и выходит за рамки JPA. Тут я не могу подсказать, может у него и поведение другое.

В JPA вместо SessionFactory используется EntityManager.
_________________
К началу Посмотреть профиль Отправить личное сообщение
Mam(O)n : 61
Новичок

СообщениеДек 30, 2011 12:22 
Ответить с цитатой
sgdread писал(а):

Есть нюансы. К примеру в Hibernate на коллекциях сиротки не удаляются. Нужно ставить свойство orphanRemoval:
Ну это какбы не ньюанс, это часть стандарта JPA. Используется это в таком случае:
Код:

Person person = new Person();
Address oldAddress = new Address();
person.set(oldAddress);
entityManager.persist(person);

Address newAddress = new Address();
person.set(newAddress);
entityManager.update(person);
// И вот теперь oldAddress "сирота" и будет уничтожен при orphanRemoval=true
К началу Посмотреть профиль Отправить личное сообщение
 
Начать новую тему  Ответить на тему
Страница 1 из 2
На страницу 1, 2  След.
Список форумов
 -> Персистентность в Java (JPA, ORM, ODB)


 
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах


Java and all Java-related trademarks and logos are trademarks or registered trademarks of Oracle Corporation in the United States and other countries.
Это сайт не относится к фирме Oracle Corporation и не поддерживается ею.

© 2006-2010 www.javatalks.ru: форум java программистов
Используется скрипт phpBB © 2001, 2010 phpBB Group

Хостинг от bizname.ru