我正忙着使用hibernate 4.2.2.Final和Spring 3.2.3.RELEASE编写应用程序。我使用日志框架log4jdbc-remix(0.2.7)来记录对数据库的所有sql调用。我正在使用hibernate标准来生成SQL语句。在一种情况下,我正在生成一个SQL语句,当我在数据库本身(DB / 2)上执行它时返回结果,只是从日志输出中复制粘贴。在休眠状态下,结果列表为空(同一查询)。
方法(我确实将变量的名称更改为更多'通用英语'名称):
@Override
public List<PersonId> getActiveNumbers(SpecialNumber specialumber) {
final Criteria criteria = this.getCurrentSession().createCriteria(Person.class);
criteria.add(Restrictions.eq("specialNr", specialNumber));
criteria.setProjection(Projections.projectionList()
.add(Projections.property("id.baseNr"))
.add(Projections.property("id.subNr")));
criteria.add(Subqueries.propertiesIn(new String[] { "id.baseNr", "id.subNr" },
isActive()));
criteria.setResultTransformer(Transformers.aliasToBean(PersonId.class));
return (List<PersonId>) criteria.list();
}
private DetachedCriteria isActive() {
DetachedCriteria isActive = DetachedCriteria.forClass(PersonSpecific.class);
isActive.add(LocalDateComposite.lessThanOrEqual("date", LocalDate.now()));
isActive.add(Restrictions.or(Restrictions.eq("dateCancel", null),
Restrictions.ge("dateCancel", LocalDate.now())));
isActive.setProjection(Projections.projectionList()
.add(Projections.property("id.baseNr").as("baseNr"))
.add(Projections.property("id.subNr").as("subNr")));
return isActive;
}
然而,当我删除该行
criteria.add(Restrictions.eq("specialNr", specialNumber));
hibernate会生成结果列表。子查询'isActive'使用正确的值返回正确的查询(根据日志,以及当我删除上面的行时)。
'specialNr'的类型为'specialNumber',我有一个自定义UserType:
public class SpecialNumberUserType extends AbstractUserType implements UserType {
private static final int[] TYPES = { Types.BIGINT };
[...]
@Override
public int[] sqlTypes() {
return TYPES;
}
@Override
public Class<?> returnedClass() {
return SpecialNumber.class;
}
@Override
public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor session, Object owner)
throws HibernateException, SQLException {
if (rs.wasNull()) {
return null;
}
return new specialNumber(rs.getLong(names[0]));
}
@Override
public void nullSafeSet(PreparedStatement st, Object value, int index,
SessionImplementor session) throws HibernateException, SQLException {
if (null == value) {
st.setLong(index, 0L);
} else {
st.setLong(index, ((SpecialNumber) value).getValue());
}
}
}
我无法弄清楚为什么hibernate会生成正确的sql,但是deos不能获取正确的结果。我在其他表和查询中使用'specialNumber',它在其他查询中也可以使用。只有在这种特殊情况下,hibernate才会获取结果。有任何想法吗?感觉好像自定义usertype SpecialNumberUserType有问题,但我无法弄清楚是什么,因为生成的sql显示正确的值,并且它在其他sql语句中使用相同的'specialNumber'类。
- 编辑:
我忘了提及:当我针对内存测试db(hsqldb)运行相同的方法时,我得到了预期的结果。所以,总结一下:
我很困惑......
- EDIT_II:
我正在尝试使用hql-queries。同样非常奇怪的问题,我只关注'specialNumber':
final Query query = this.getCurrentSession().createQuery(
"select * from Person where specialNumber = 436260171");
给出了预期的结果。 (在这种情况下2条记录)。当我将其更改为:
final Query query = this.getCurrentSession().createQuery(
"select * from Person where specialNumber = :specialNumber");
query.setLong("specialNumber", 436260171L);
或
query.setParameter("specialNumber", new SpecialNumber(436260171L));
我再次获得一个空列表。因此,使用参数突然,它不再起作用。我不明白:p。
答案 0 :(得分:0)
最后,解决了它。显然在(遗留)数据库端,数据类型是CHAR。在内存中测试数据库中,类型被映射到整数。这就是为什么它在“内存”中工作,而不是真正的数据库。我不得不更改usertype的nullSafeSet方法,使其正常工作......
编辑: 更糟糕的是:'SpecialNumber'在不同的表中被定义为不同的类型:在一个表上,它是一个char(N),在另一个表中,它是一个bigint。现在一切都工作了(我想)。