我正忙于使用 hibernate 4.2.2.Final 和 Spring 3.2.3.RELEASE 编写应用程序。我使用日志框架 log4jdbc-remix (0.2.7) 来记录对数据库的所有 sql 调用。我正在使用休眠条件来生成 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());
}
}
}
我无法弄清楚为什么休眠确实会生成正确的 sql,但无法获取正确的结果。我确实在其他表和查询中使用了“specialNumber”,它在其他查询中也有效。只有在这种特殊情况下,hibernate 才不会获取结果。有任何想法吗?感觉好像自定义用户类型 SpecialNumberUserType 有问题,但我不知道是什么,因为生成的 sql 显示了正确的值,并且它在使用相同的“specialNumber”类的其他 sql 语句中工作。
- 编辑:
我忘了提一下:当我对内存中的测试数据库(hsqldb)运行相同的方法时,我确实得到了预期的结果。所以,总结一下:
- 生成的 sql 没问题,值正确(检查日志);
- 直接在数据库(db/2终端)上运行生成的sql,得到了预期的结果;
- 对内存数据库运行方法“getActiveNumbers”,我得到了预期的结果;
- 对真实数据库运行方法“getActiveNumbers”,我得到一个空列表,这不是预期的结果。
- 运行相同的方法,但具有行 'criteria.add(Restrictions.eq("specialNr", specialNumber));' 删除,我确实得到了该查询的预期结果(这是相当多的行);
- 使用相同的“SpecialNumber”类作为另一个类的属性对真实数据库运行其他查询(使用休眠条件)确实有效 - 这里没有显示代码,但它非常相似,有一行像 'criteria.add(Restrictions. eq("specialNr", specialNumber));'.
我很困惑...
-- EDIT_II:
我正试图让它与 hql 查询一起使用。同样非常奇怪的问题,我只关注'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。