как решить jpa и hibernate один в один анонс с doSecondPass Exception - PullRequest
1 голос
/ 08 декабря 2011

Привет, я пишу простой код, который вставляет данные в две таблицы, используя jpa и версию Hibernate 3.2. Моя задача - сохранить данные сотрудника в двух таблицах, то есть Employee, который содержит employeeId, который является первичным ключом, которому назначено назначенное значение вручную, и адрес сотрудника. которые разделяют первичный ключ employeeId в таблице Employee с помощью аннотаций @onetoOne. Мои классы выглядят как

@Entity
@Table(name = "employee", catalog = "test", uniqueConstraints = {})
public class Employee implements java.io.Serializable {

    // Fields

    private Integer employeeid;

    private String name;

    private Employeeaddress employeeaddress;
    // Constructors

    /** default constructor */
    public Employee() {
    }

    /** minimal constructor */
    public Employee(Integer employeeid) {
        this.employeeid = employeeid;
    }

    /** full constructor */
    public Employee(Integer employeeid, String name) {
        this.employeeid = employeeid;
        this.name = name;
    }

    // Property accessors
    @Id
    @Column(name = "EMPLOYEEID", unique = true, nullable = false, insertable = true, updatable = true)
    public Integer getEmployeeid() {
        return this.employeeid;
    }

    public void setEmployeeid(Integer employeeid) {
        this.employeeid = employeeid;
    }

    @Column(name = "NAME", unique = false, nullable = true, insertable = true, updatable = true, length = 45)
    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @OneToOne(mappedBy="employee")
    @PrimaryKeyJoinColumn
    public Employeeaddress getEmployeeaddress() {
        return employeeaddress;
    }

    public void setEmployeeaddress(Employeeaddress employeeaddress) {
        this.employeeaddress = employeeaddress;
    }
}


@Entity
@Table(name = "employeeaddress", catalog = "test", uniqueConstraints = {})
public class Employeeaddress implements java.io.Serializable {

    // Fields

    private Integer employeeid;

    private String address;

    private Employee employee;
    // Constructors

    /** default constructor */
    public Employeeaddress() {
    }

    /** minimal constructor */
    public Employeeaddress(Integer employeeid) {
        this.employeeid = employeeid;
    }

    /** full constructor */
    public Employeeaddress(Integer employeeid, String address) {
        this.employeeid = employeeid;
        this.address = address;
    }

    // Property accessors
    @Id
    @Column(name = "EMPLOYEEID", unique = true, nullable = false, insertable = true, updatable = true)
    public Integer getEmployeeid() {
        return this.employeeid;
    }

    public void setEmployeeid(Integer employeeid) {
        this.employeeid = employeeid;
    }

    @Column(name = "ADDRESS", unique = false, nullable = true, insertable = true, updatable = true, length = 45)
    public String getAddress() {
        return this.address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @OneToOne(mappedBy="employeeaddress")
    @PrimaryKeyJoinColumn
    public Employee getEmployee() {
        return employee;
    }

    public void setEmployee(Employee employee) {
        this.employee = employee;
    }

}

и мой основной класс

public class EmployeeDao {
    public static void main(String[] args) {
        try{
        AnnotationConfiguration cfg = new AnnotationConfiguration();
        cfg.addAnnotatedClass(employeeforms.Employee.class);
        cfg.addAnnotatedClass(employeeforms.Employeeaddress.class);
        SessionFactory sessionFactory = cfg.buildSessionFactory();
        Session session =sessionFactory.openSession();
        Employee e = new Employee();
        e.setEmployeeid(100872);
        e.setName("sandeep");
        Employeeaddress ed = new Employeeaddress();     
        ed.setAddress("Hyderabad");
        e.setEmployeeaddress(ed);
        session.save(e);
        }catch (Exception e) {
            e.printStackTrace();
        }
    }

}

когда я запускаю свой основной класс, я получаю исключения ниже

java.lang.NullPointerException
    at org.hibernate.cfg.OneToOneSecondPass.doSecondPass(OneToOneSecondPass.java:135)
    at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1130)
    at org.hibernate.cfg.AnnotationConfiguration.secondPassCompile(AnnotationConfiguration.java:296)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1286)
    at employeeDao.EmployeeDao.main(EmployeeDao.java:16)

мои столы

    CREATE TABLE  employee (
      EMPLOYEEID int(10) unsigned NOT NULL ,
      NAME varchar(45) default '',
      PRIMARY KEY  (EMPLOYEEID`)
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1;

    CREATE TABLE  employeeaddress (
      EMPLOYEEID int(10) unsigned NOT NULL default '0',
      ADDRESS varchar(45) default '',
      PRIMARY KEY  (EMPLOYEEID)
    ) ENGINE=InnoDB 
DEFAULT CHARSET=latin1;

Ответы [ 2 ]

1 голос
/ 08 декабря 2011

У вас есть (как минимум) три проблемы.

Первая проблема: вы указываете

@OneToOne(mappedBy="employee")
@PrimaryKeyJoinColumn

и

@OneToOne(mappedBy="employeeaddress")
@PrimaryKeyJoinColumn

Эти две аннотации противоречивы;если установлено mappedBy, это означает, что информация о сопоставлении находится на другой стороне.Только одна сторона должна определять отображение (@PrimaryKeyJoinColumn), а другая сторона должна устанавливать атрибут mappedBy.

Вторая проблема: вы указываете

Employeeaddress ed = new Employeeaddress();     
ed.setAddress("Hyderabad");
e.setEmployeeaddress(ed);

Обе стороны ассоциацийдолжен быть инициализирован. Код должен:

e.setEmployeeaddress(ed);
ed.setEmployee(e);

Hibernate использует сторону, где mappedBy равен , а не , чтобы узнать, существует ли связь.

Вы сохраняете сотрудника, но не сохраняете адрес. И нет каскадного набора от сотрудника к адресу.

0 голосов
/ 08 декабря 2011

На основе этих 3,6-дневных документов гибернации ваше отображение должно выглядеть следующим образом:

@Entity
@Table(name = "employee", catalog = "test", uniqueConstraints = {})
public class Employee implements java.io.Serializable {

    private Integer employeeid;
    private Employeeaddress employeeaddress;
    // other fields and constructors

    @Id
    @Column(name = "EMPLOYEEID", unique = true, nullable = false, insertable = true, updatable = true)
    public Integer getEmployeeid() {
        return this.employeeid;
    }

    public void setEmployeeid(Integer employeeid) {
        this.employeeid = employeeid;
    }


    @OneToOne(mappedBy="employee")
    public Employeeaddress getEmployeeaddress() {
        return employeeaddress;
    }

    public void setEmployeeaddress(Employeeaddress employeeaddress) {
        this.employeeaddress = employeeaddress;
    }
}


@Entity
@Table(name = "employeeaddress", catalog = "test", uniqueConstraints = {})
public class Employeeaddress implements java.io.Serializable {

    private Integer employeeid;
    private Employee employee;

    @Id
    @Column(name = "EMPLOYEEID", unique = true, nullable = false, insertable = true, updatable = true)
    public Integer getEmployeeid() {
        return this.employeeid;
    }
    // EDIT: private setter for employeeid, id is set by setEmployee() but hibernate needs a setter to initialize the instance on load
    private void setEmployeeid(Integer id) {
        this.employeeid = id;
    }


    @OneToOne
    @MapsId
    public Employee getEmployee() {
        return employee;
    }

    public void setEmployee(Employee employee) {
        this.employee = employee;
    }

}

EDIT: Аннотация @MapsId была введена в JPA 2.0 (реализована в спящем с 3.5, я думаю). Если вы используете более старую версию Hibernate, в которой не реализована спецификация JPA 2.0, вы можете сопоставить один и тот же идентификатор для двух объектов, подобных этой (класс Employee остается без изменений):

@Entity
@Table(name = "employeeaddress", catalog = "test", uniqueConstraints = {})
public class Employeeaddress implements java.io.Serializable {

    private Integer employeeid;
    private Employee employee;

    @Id
    @GeneratedValue(generator = "anyName")
    @GenericGenerator(name = "anyName", strategy = "foreign", parameters = { @Parameter(name = "property", value = "employee") })
    @Column(name = "EMPLOYEEID", unique = true, nullable = false, insertable = true, updatable = true)
    public Integer getEmployeeid() {
        return this.employeeid;
    }
    // EDIT: private setter for employeeid, id is set by setEmployee() but hibernate needs a setter to initialize the instance on load
    private void setEmployeeid(Integer id) {
        this.employeeid = id;
    }   

    @OneToOne
    @PrimaryKeyJoinColumn
    public Employee getEmployee() {
        return employee;
    }

    public void setEmployee(Employee employee) {
        this.employee = employee;
    }

}

Вы также должны сначала сохранить временный / отключенный экземпляр Employeeaddress перед сохранением связанного временного / отключенного экземпляра Employee или изменить аннотацию в классе Employee на каскадное сохранение:

@OneToOne(mappedBy="employee", cascade = CascadeType.SAVE_UPDATE)
public Employeeaddress getEmployeeaddress() {
    return employeeaddress;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...