Hibernate4不从数据库中获取数据

时间:2013-08-09 13:59:59

标签: sql spring hibernate criteria usertype

我正忙着使用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)运行相同的方法时,我得到了预期的结果。所以,总结一下:

  1. 生成的sql正常,使用正确的值(检查日志);
  2. 直接在数据库(db / 2终端)上运行生成的sql,得到预期的结果;
  3. 针对内存数据库运行方法'getActiveNumbers',我得到了预期的结果;
  4. 对真实数据库运行方法'getActiveNumbers',我得到一个空列表,这不是预期的结果。
  5. 运行相同的方法,但行'criteria.add(Restrictions.eq(“specialNr”,specialNumber));'删除后,我确实得到了该查询的预期结果(这是很多行);
  6. 运行其他查询(使用hibernate条件)使用相同的'SpecialNumber'类作为另一个类的属性对真实数据库确实有效 - 这里没有显示代码,但它非常相似,有一条像'criteria.add这样的行(Restrictions.eq(“specialNr”,specialNumber));'。
  7. 我很困惑......

    - 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。

1 个答案:

答案 0 :(得分:0)

最后,解决了它。显然在(遗留)数据库端,数据类型是CHAR。在内存中测试数据库中,类型被映射到整数。这就是为什么它在“内存”中工作,而不是真正的数据库。我不得不更改usertype的nullSafeSet方法,使其正常工作......

编辑: 更糟糕的是:'SpecialNumber'在不同的表中被定义为不同的类型:在一个表上,它是一个char(N),在另一个表中,它是一个bigint。现在一切都工作了(我想)。