您的位置:首页 > 其它

hibernate 中 addEntity() 与 @Formula 注解同时使用是遇到的问题

2016-11-25 19:25 281 查看
今天使用hibernate 的 createSQLQuery 方法, 使用原生sql查询数据, 本来想直接使用 query.addEntity("${p.*}", Student.class) 将结果封装成实体, 但是程序在 query.list() 方法中一直报 空指针异常, 

 java.lang.NullPointerException
at org.hibernate.loader.DefaultEntityAliases.intern(DefaultEntityAliases.java:186)
at org.hibernate.loader.DefaultEntityAliases.getSuffixedPropertyAliases(DefaultEntityAliases.java:149)
at org.hibernate.loader.DefaultEntityAliases.determinePropertyAliases(DefaultEntityAliases.java:93)
at org.hibernate.loader.DefaultEntityAliases.<init>(DefaultEntityAliases.java:65)
at org.hibernate.loader.ColumnEntityAliases.<init>(ColumnEntityAliases.java:43)
at org.hibernate.loader.custom.sql.SQLQueryReturnProcessor.generateCustomReturns(SQLQueryReturnProcessor.java:222)
at org.hibernate.loader.custom.sql.SQLCustomQuery.<init>(SQLCustomQuery.java:153)
at org.hibernate.engine.query.internal.NativeQueryInterpreterStandardImpl.createQueryPlan(NativeQueryInterpreterStandardImpl.java:84)
at org.hibernate.engine.query.spi.QueryPlanCache.getNativeSQLQueryPlan(QueryPlanCache.java:226)
at org.hibernate.internal.AbstractSessionImpl.getNativeSQLQueryPlan(AbstractSessionImpl.java:305)
at org.hibernate.internal.AbstractSessionImpl.list(AbstractSessionImpl.java:311)
at org.hibernate.internal.SQLQueryImpl.list(SQLQueryImpl.java:141)

进入到 DefaultEntityAliases.java 源码. 发现是在 intern 方法中的 string[] 数组的值为 null 引起的, 通过断点, 发现这个方法里的值对应的是查询实体在数据库中对应的列名, 但是有一个是null, 通过排查发现, 是在一个属性的 getter 方法上使用了 @Formula 注解, 因此这个属性在数据库中没有对应的字段,  导致hibernate 获取 @column 注解中的 name的值的时候, 获取的是 null , 所以会报空指针异常

因为只是练习项目, 所以尽管 @Formula 的效率不高, 但是还是不想去掉, 所以想了一个笨办法, 因为查询不需要查询所有字段, 所以可以指定属性进行查询

例如 : select s.name, s.age from student s;

this.currentSession().createSQLQuery(sql).setResultTransformer(Transformers.aliasToBean(Student.class));

这样查询到的结果就会自动封装到Student类中, 当然, 只会封装指定查询的字段 name, age

但是遇到数据库数据类型与java中的数据类型不匹配的时候会出现bug, 例如mysql数据库中的 tinyint 类型对应的是java中的 Byte类型, 不过有时候我习惯都在java中使用Integer类型, 这样就会报错, 就会用到 addScalar 方法, 例如 query.addScalar("status", IntegerType.INSTANCE).addScalar("expireTime", DbTimestampType.INSTANCE),

(Hibernate4 中时这样的写法, 貌似hibernate3中用的是 Hibernate.Integer, ), 如果有一个属性需要转换, 那么所有要查询的属性都要用addScalar 方法进行映射, 否则不能查询出属性的值, 封装到对象中就是 null

注意: 这样的方法是不能封装对象属性的, 我验了一下, 没有成功, 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: