今天在写Hibernate 双向一对一的映射关系的demo时,报了这么一个弟弟,废话不多说,直接上
org.hibernate.id.IdentifierGenerationException: attempted to assign id from null one-to-one property [com.lzy.domain.Person.identity]
先上我的错误代码,各位看官看看能不能找到问题在哪。答案稍后我再揭晓。
@Test
public void function6(){
Session session = HibernateUtil.getSession();
Transaction transaction=session.beginTransaction();
Person person = new Person();
person.setPname("ll");
System.out.println(person);
session.save(person);
Identity identity = new Identity();
person.setIdentity(identity);
identity.setPerson(person);
session.save(identity);
transaction.commit();
HibernateUtil.closeSession();
}
下面是Person代码
package com.lzy.domain;
public class Person {
private Integer pid;
private String pname;
private Identity identity;
public Person(){}
public Integer getPid() {
return pid;
}
public void setPid(Integer pid) {
this.pid = pid;
}
public String getPname() {
return pname;
}
public void setPname(String pname) {
this.pname = pname;
}
public Identity getIdentity() {
return identity;
}
public void setIdentity(Identity identity) {
this.identity = identity;
}
@Override
public String toString() {
return "Person [pid=" + pid + ", pname=" + pname + ", identity=" + identity + "]";
}
}
Person的xml配置
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- 配置表与实体对象的关系 -->
<hibernate-mapping package="com.lzy.domain" >
<class name="Person" table="person" >
<id name="pid" >
<column name="pid"/>
<generator class="foreign">
<param name="property">identity</param>
</generator>
</id>
<property name="pname" column="pname" >
<!-- <column name="cust_name" sql-type="varchar" ></column> -->
</property>
<one-to-one name="identity" class="Identity" constrained="true">
</one-to-one>
</class>
</hibernate-mapping>
再贴上Identity代码:
package com.lzy.domain;
public class Identity {
private Integer id;
private Person person;
public Identity(){}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
}
还有Identity的xml配置
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- 配置表与实体对象的关系 -->
<hibernate-mapping package="com.lzy.domain" >
<class name="Identity" table="identity" >
<id name="id">
<column name="id"></column>
<generator class="native">
</generator>
</id>
<one-to-one name="person" class="Person" cascade="all"></one-to-one>
</class>
</hibernate-mapping>
报错的是在session.save(person);
看到这个错误,首先想到的就是id是空,毕竟弟弟都这么说了
我的Person的主键用的是Identity的主键,Person本身不具备主键生成策略,所以在保存的时候,当Hibernate提取Person对象的PID属性的时候,就报错了,从一个空的property提取id,这时候怎么办呢?
既然弟弟都说没有ID了,那么我们就给他一个ID好了,但是Person自己是没有ID的,那么只好先创建一个Identity,然后通过Person.setIdentity(),去把Identity的ID赋值给Person
但是仅仅这样还是会报错的,为什么,同样的道理,我们还需要把Person赋值给Identity
代码如下:
@Test
public void function6(){
Session session = HibernateUtil.getSession();
Transaction transaction=session.beginTransaction();
Person person = new Person();
person.setPname("ll");
Identity identity = new Identity();
person.setIdentity(identity);
identity.setPerson(person);
session.save(identity);
transaction.commit();
HibernateUtil.closeSession();
}
点击Run As,又看到了让人心旷神怡的那一抹绿色,大功告成!
总结:
不管是一对一,一对多还是多对多,在进行保存的时候,如果自身没有主键生成策略,那么就必须要先将主表的对象创建好,通过set方法赋值给自己,让自己能有个主键之后,再去save.