前两天我微博提到有个BUG出现了两个月却还没有头绪。这个BUG是这样的:在Hibernate中自定义UserType,从数据库中取值的时候,有时候这个UserType能取到值,但有时候即使数据库有值,取到的也是null。后来负责前端的同事偶然发现,当数据库中某些字段为null的时候,这个UserType就取不到值,如果把这些字段填上内容,就可以取到了。于是这个问题就莫名其妙地解决了。后来经过分析和测试,发现只要UserType的前一个字段为null,这个UserType就肯定取不到值。UserType的代码是这样的:
public class GenderUserType extends StringUserType { public Class returnedClass() { return Gender.class; } public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws HibernateException, SQLException { if (rs.wasNull()) return null; String gender = rs.getString(names[0]); return Gender.valueOf(gender); } public void nullSafeSet(PreparedStatement st, Object value, int index) throws HibernateException, SQLException { if (value == null) { st.setNull(index, SQL_TYPE); } else { String gender = ((Gender)value).toString(); st.setString(index, gender); } } }
您能看出问题在哪了吗?对了,就是nullSafeGet里的if (rs.wasNull()) return null;这句。查看wasNull的文档不难发现,这个方法用于判断上次从rs中取出的值是否为null。因此,如果这个UserType的前一个字段为null,这条语句就会返回null。当时我不知道从哪copy了这份代码,于是产生了这样一个表现十分诡异的BUG。
要修复这个BUG是很简单的,只需要调换nullSafeGet里前两行代码即可。
如果UserType是除主键外的第一个字段,在取值的时候还会产生“sqlexception 未读取数据”的异常。
http://topic.csdn.net/u/20110713/22/5b9384fa-91ff-4086-a83c-90c89b355e19.html