如何使用doSecondPassexception解决jpa和hibernate一对一注释

您好我正在编写简单的代码,使用jpa和Hibernate 3.2版本将数据插入到两个表中。我的意图是将Employee详细信息保存在两个表中,即Employee包含employeeId,这是主键,手动分配指定值和Employee Address共享使用@onetoOne annotions的Employee表中的主键employeeId。我的类就像lool一样

@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(); } } } 

当我运行我的主要课程时,我得到以下exception

 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; 

你有(至少)三个问题。

第一个问题:你指定

 @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的一侧来知道是否存在关联。

第三个问题:

您保存员工,但不保存地址。 从员工到地址都没有级联设置。

基于这些hibernate 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; } } 

编辑: @MapsId注释是用JPA 2.0引入的(我认为自3.5以来在hibernate中实现)。 如果您使用的是未实现JPA 2.0规范的较旧的hibernate版本,则可以为这样的两个实体映射相同的id(类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; } } 

在保存关联的瞬态/分离的Employee实例或将类Employee的注释更改为级联保存之前,还必须先保存瞬态/分离的Employeeaddress实例:

 @OneToOne(mappedBy="employee", cascade = CascadeType.SAVE_UPDATE) public Employeeaddress getEmployeeaddress() { return employeeaddress; }