按示例和投影进行休眠查询

2022-09-02 00:12:17

简而言之:休眠不支持投影和按示例查询?我发现这篇文章:

代码是这样的:

User usr = new User();
usr.setCity = 'TEST';
getCurrentSession().createCriteria(User.class)
.setProjection( Projections.distinct( Projections.projectionList()
.add( Projections.property("name"), "name")
.add( Projections.property("city"), "city")))
.add( Example.create(usr))

就像另一张海报说的,生成的sql一直有一个where类引用y0_=?而不是this_.city

我已经尝试了几种方法,并搜索了问题跟踪器,但对此一无所知。

我甚至尝试使用投影别名和变形金刚,但它不起作用:

User usr = new User();
usr.setCity = 'TEST';
getCurrentSession().createCriteria(User.class)
.setProjection( Projections.distinct( Projections.projectionList()
.add( Projections.property("name"), "name")
.add( Projections.property("city"), "city")))
.add( Example.create(usr)).setResultTransformer(Transformers.aliasToBean(User.class));

是否有人使用投影和查询示例?


答案 1

当您的别名与 objects 属性同名时,似乎会出现此问题。Hibernate似乎拾取别名并在sql中使用它。我在这里这里发现了这一点,我相信这是Hibernate中的一个错误,尽管我不确定Hibernate团队是否同意。

无论哪种方式,我都找到了一个简单的解决方法,适用于我的情况。您的里程可能会有所不同。详细信息如下,我试图简化此示例的代码,因此我对任何错误或拼写错误表示歉意:

Criteria criteria = session.createCriteria(MyClass.class)
    .setProjection(Projections.projectionList()
        .add(Projections.property("sectionHeader"), "sectionHeader")
        .add(Projections.property("subSectionHeader"), "subSectionHeader")
        .add(Projections.property("sectionNumber"), "sectionNumber"))
    .add(Restrictions.ilike("sectionHeader", sectionHeaderVar)) // <- Problem!
    .setResultTransformer(Transformers.aliasToBean(MyDTO.class));

将生成以下 sql:

select
    this_.SECTION_HEADER as y1_,
    this_.SUB_SECTION_HEADER as y2_,
    this_.SECTION_NUMBER as y3_,
from
    MY_TABLE this_ 
where
    ( lower(y1_) like ? ) 

导致错误:java.sql.SQLException: ORA-00904: “Y1_”: 标识符无效

但是,当我将限制更改为使用“this”时,如下所示:

Criteria criteria = session.createCriteria(MyClass.class)
    .setProjection(Projections.projectionList()
        .add(Projections.property("sectionHeader"), "sectionHeader")
        .add(Projections.property("subSectionHeader"), "subSectionHeader")
        .add(Projections.property("sectionNumber"), "sectionNumber"))
    .add(Restrictions.ilike("this.sectionHeader", sectionHeaderVar)) // <- Problem Solved!
    .setResultTransformer(Transformers.aliasToBean(MyDTO.class));

它产生了以下sql,我的问题得到了解决。

select
    this_.SECTION_HEADER as y1_,
    this_.SUB_SECTION_HEADER as y2_,
    this_.SECTION_NUMBER as y3_,
from
    MY_TABLE this_ 
where
    ( lower(this_.SECTION_HEADER) like ? ) 

就是这样,它!一个非常简单的解决痛苦的问题。我不知道这个修复程序将如何转化为示例查询问题,但它可能会让你更接近。


答案 2

我可以看到你们的用户类吗?这只是使用下面的限制。我不明白为什么限制与示例有什么不同(我认为在示例中默认情况下会忽略空字段)。

getCurrentSession().createCriteria(User.class)
.setProjection( Projections.distinct( Projections.projectionList()
.add( Projections.property("name"), "name")
.add( Projections.property("city"), "city")))
.add( Restrictions.eq("city", "TEST")))
.setResultTransformer(Transformers.aliasToBean(User.class))
.list();

我从未使用过alaistToBean,但我刚刚阅读了它。您也可以循环访问结果。

List<Object> rows = criteria.list();
for(Object r: rows){
  Object[] row = (Object[]) r;
  Type t = ((<Type>) row[0]);
}

如果必须,您可以以这种方式手动填充用户。

如果没有更多的信息来诊断问题,就很难研究这个问题。


推荐