在 孙卫勤 的 Hibernate 一书中,关于 UserType 的使用举了很多例子,其中一个是 Integer 到 VARCHAR 类型的
自定义映射。
Customer 类中有一个 private Integer phone; 类型的属性,通过自定义类型 Integer2VARCHAR 将其映射到数据库
的VARCHAR类型。
在测试类中, session.save(customer); 能够正常运行;
但是,在 Customer c = (Customer) session.load(Customer.class, id); 中却抛出异常,Hibernate Debug级别的日志片段如下:
java.sql.SQLException: 未读取数据
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:145) [ojdbc14_g.jar:Oracle JDBC Driver version - "10.2.0.1.0XE"]
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:190) [ojdbc14_g.jar:Oracle JDBC Driver version - "10.2.0.1.0XE"]
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:286) [ojdbc14_g.jar:Oracle JDBC Driver version - "10.2.0.1.0XE"]
at oracle.jdbc.driver.OracleStatement.wasNullValue(OracleStatement.java:3989) [ojdbc14_g.jar:Oracle JDBC Driver version - "10.2.0.1.0XE"]
at oracle.jdbc.driver.OracleResultSetImpl.wasNull(OracleResultSetImpl.java:136) [ojdbc14_g.jar:Oracle JDBC Driver version - "10.2.0.1.0XE"]
at rayleeya.hibernate.usertype.customtype.Integer2VARCHAR.nullSafeGet(Integer2VARCHAR.java:55) [bin/:na]
at org.hibernate.type.CustomType.nullSafeGet(CustomType.java:105) [hibernate3.jar:na]
at org.hibernate.type.AbstractType.hydrate(AbstractType.java:81) [hibernate3.jar:na]
at org.hibernate.persister.entity.AbstractEntityPersister.hydrate(AbstractEntityPersister.java:2101) [hibernate3.jar:na]
at org.hibernate.loader.Loader.loadFromResultSet(Loader.java:1381) [hibernate3.jar:na]
at org.hibernate.loader.Loader.instanceNotYetLoaded(Loader.java:1309) [hibernate3.jar:na]
at org.hibernate.loader.Loader.getRow(Loader.java:1207) [hibernate3.jar:na]
at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:580) [hibernate3.jar:na]
at org.hibernate.loader.Loader.doQuery(Loader.java:701) [hibernate3.jar:na]
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:236) [hibernate3.jar:na]
at org.hibernate.loader.Loader.loadEntity(Loader.java:1858) [hibernate3.jar:na]
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:48) [hibernate3.jar:na]
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:42) [hibernate3.jar:na]
at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:3049) [hibernate3.jar:na]
at org.hibernate.event.def.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:411) [hibernate3.jar:na]
at org.hibernate.event.def.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:392) [hibernate3.jar:na]
at org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java:142) [hibernate3.jar:na]
at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:98) [hibernate3.jar:na]
at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:882) [hibernate3.jar:na]
at org.hibernate.impl.SessionImpl.immediateLoad(SessionImpl.java:840) [hibernate3.jar:na]
at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:66) [hibernate3.jar:na]
at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:111) [hibernate3.jar:na]
at org.hibernate.proxy.pojo.cglib.CGLIBLazyInitializer.invoke(CGLIBLazyInitializer.java:150) [hibernate3.jar:na]
at rayleeya.hibernate.usertype.entities.Customer$$EnhancerByCGLIB$$baad4d72.toString(<generated>) [cglib-nodep-2.1_3.jar:na]
at java.lang.String.valueOf(String.java:2827) [na:1.6.0_10]
at java.io.PrintStream.println(PrintStream.java:771) [na:1.6.0_10]
at rayleeya.hibernate.usertype.EventManager.updateCustomer(EventManager.java:44) [bin/:na]
at rayleeya.hibernate.usertype.EventManager.main(EventManager.java:55) [bin/:na]
我的数据库是 OracleXE, 数据库自带的驱动有两个,ojdbc14_g.jar 和 ojdbc14.jar, 看日志的话好像是 驱动有问题,
但是很奇怪,我的例子中有四个自定义映射类型的属性(phone, address, gender, name ):
public class Customer {
private Long id;
private Integer phone;
private Address address;
private Gender gender;
private Name name;
public Long getId() {
return id;
}
private void setId(Long id) {
this.id = id;
}
// 省略其他 Getter & Setter...
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("id : ").append(id).append("\n").append("phone : ").append(phone).append("\n").append("address : ").append(address).append("\n").append("gender : ").append(gender).append("\n").append("name : ").append(name);
return sb.toString();
}
}
phone : Integer -- VARCHAR,其他三个都不是基本类型。
integer2VARCHAR 的 nullSafeGet() 方法是 :
public Object nullSafeGet(ResultSet rs, String[] names, Object owner)
throws HibernateException, SQLException {
if (rs.wasNull()) return null; //关键就是这句,如果注释掉的话就能正常运行;
String ret = rs.getString(names[0]);
return new Integer(ret);
}
问题原因继续研究。