前两天,做了一个Hibernate one-to-one的Demo,来示例级联更新;本来这么简单的事情,是绝对不会出问题的,可没想到一个小小的疏忽,导致出现了问题;问题的现象是数据不能级联保存且并没有出现异常。这个问题花费了我好几个小时的时间调试才解决,最后才发现犯了一个极其愚蠢的错误,特意记下来,警告自己。
Demo是Hibernate的典型例子,一个TUser对象,一个TPassport的对象
TUser和TPassport是主键的一对一关系;
TUser.java 和 TUser.hbm.xml文件内容如下:
package com.hr;
import java.io.Serializable;
public class TUser implements Serializable {
public Integer id;
public Integer age;
public String name;
public TPassport passport;
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public TPassport getPassport() {
return passport;
}
public void setPassport(TPassport passport) {
passport = passport;
}
}
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.hr.TUser" table="T_USER">
<id name="id" column="id" type="integer" unsaved-value="null">
<generator class="native"></generator>
</id>
<property name="age" column="age" type="integer"></property>
<property name="name" column="name" type="string"></property>
<one-to-one name="passport" class="com.hr.TPassport" cascade="save-update" outer-join="false"></one-to-one>
</class>
</hibernate-mapping>
TPassportr.java 和 TPassportr.hbm.xml文件内容如下:
package com.hr;
import java.io.Serializable;
public class TPassport implements Serializable {
public Integer id;
public String serial;
public Integer expriy;
public TUser user;
public TUser getUser() {
return user;
}
public void setUser(TUser tuser) {
this.user = tuser;
}
public Integer getExpriy() {
return expriy;
}
public void setExpriy(Integer expriy) {
this.expriy = expriy;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getSerial() {
return serial;
}
public void setSerial(String serial) {
this.serial = serial;
}
}
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.hr.TPassport" table="T_PASSPORT">
<id name="id" column="id" type="integer" unsaved-value="null">
<generator class="foreign">
<param name="property">user</param>
</generator>
</id>
<property name="serial" column="serial" type="string"></property>
<property name="expriy" column="expriy" type="integer"></property>
<one-to-one name="user" class="com.hr.TUser" constrained="true"></one-to-one>
</class>
</hibernate-mapping>
TestCase测试代码如下:
Configuration config = new Configuration().configure();
config.addClass(TUser.class);
config.addClass(TPassport.class);
SessionFactory sf = config.buildSessionFactory();
Session session = sf.openSession();
TUser user = new TUser();
user.setId(100);
user.setAge(13);
user.setName("Tom");
TPassport passport = new TPassport();
passport.setSerial("CN9895");
passport.setExpriy(201010);
user.setPassport(passport);
passport.setUser(user);
Transaction tx = session.beginTransaction();
session.save(user);
tx.commit();
session.close();
sf.close();
最后出现的现象是Tuser保存成功,但是TPassport没有能级联保存,且应用运行正常,没有抛出任何异常。检查代码和配置文件(重点检查了配置文件)没有发现任何问题,经过艰苦的调试;跟踪到Hibernate代码中,发现在save之前user.passport 的值竟然为null,于是重点查看了TUser类终于发现了问题在下面的函数setPassport中竟然为passport = passport;
如下:
public void setPassport(TPassport passport) {
passport = passport;
}
正确的代码为:
public void setPassport(TPassport passport) {
this.passport = passport;
}
当然赋值语句不能给this.passport赋值了.这种问题本来是小问题,但是由于很少会注意Pojo对象的问题,感觉太简单不可能出问题,所以很难调试。再一次警告自己。