简体   繁体   English

Hibernate查询示例和预测

[英]Hibernate Query By Example and Projections

To make it short: hibernate doesn't support projections and query by example? 简而言之:hibernate不支持投影和查询示例? I found this post: 我发现这篇文章:

The code is this: 代码是这样的:

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

Like the other poster said, The generated sql keeps having a where class refering to just y0_= ? 就像另一张海报所说的那样,生成的sql继续有一个where类引用y0_ =? instead of this_.city . 而不是this_.city

I already tried several approaches, and searched the issue tracker but found nothing about this. 我已经尝试了几种方法,并搜索了问题跟踪器,但没有发现任何相关信息。

I even tried to use Projection alias and Transformers, but it does not work: 我甚至尝试使用Projection别名和变形金刚,但它不起作用:

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));

Has anyone used projections and query by example ? 有没有人用例子进行投影和查询?

The problem seems to happen when you have an alias the same name as the objects property. 当您具有与objects属性相同的别名时,似乎会发生此问题。 Hibernate seems to pick up the alias and use it in the sql. Hibernate似乎拿起了别名并在sql中使用它。 I found this documented here and here , and I believe it to be a bug in Hibernate, although I am not sure that the Hibernate team agrees. 我在这里这里发现了这个,我相信它是Hibernate中的一个错误,虽然我不确定Hibernate团队是否同意。

Either way, I have found a simple work around that works in my case. 无论哪种方式,我发现一个简单的工作在我的情况下工作。 Your mileage may vary. 你的旅费可能会改变。 The details are below, I tried to simplify the code for this sample so I apologize for any errors or typo's: 详细信息如下,我试图简化此示例的代码,所以我为任何错误或拼写错误道歉:

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));

Would produce this sql: 会产生这个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 ? ) 

Which was causing an error: java.sql.SQLException: ORA-00904: "Y1_": invalid identifier 导致错误的原因是: java.sql.SQLException:ORA-00904:“Y1_”:标识符无效

But, when I changed my restriction to use "this", like so: 但是,当我改变我的限制使用“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));

It produced the following sql and my problem was solved. 它产生了以下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 ? ) 

Thats, it! 而已! A pretty simple fix to a painful problem. 解决痛苦问题的一个非常简单的方法。 I don't know how this fix would translate to the query by example problem, but it may get you closer. 我不知道这个修复程序如何转换为查询示例问题,但它可能会让你更接近。

Can I see your User class? 我可以看到你的用户类吗? This is just using restrictions below. 这只是使用下面的限制。 I don't see why Restrictions would be really any different than Examples (I think null fields get ignored by default in examples though). 我不明白为什么限制与实例有任何不同(我认为在示例中默认情况下会忽略空字段)。

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();

I've never used the alaistToBean, but I just read about it. 我从未使用过alaistToBean,但我只是读过它。 You could also just loop over the results.. 你也可以循环结果..

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

If you have to you can manually populate User yourself that way. 如果必须,您可以自己手动填充用户。

Its sort of hard to look into the issue without some more information to diagnose the issue. 如果没有更多信息来诊断问题,很难调查问题。

The real problem here is that there is a bug in hibernate where it uses select-list aliases in the where-clause: 这里真正的问题是hibernate中存在一个错误,它在where子句中使用select-list别名:

http://opensource.atlassian.com/projects/hibernate/browse/HHH-817 http://opensource.atlassian.com/projects/hibernate/browse/HHH-817

Just in case someone lands here looking for answers, go look at the ticket. 万一有人在这里寻找答案,去看看票。 It took 5 years to fix but in theory it'll be in one of the next releases and then I suspect your issue will go away. 花了5年时间修复,但理论上它将在下一个版本之一,然后我怀疑你的问题会消失。

ProjectionList pl = Projections.projectionList();
pl.add(Projections.property("id"));
pl.add(Projections.sqlProjection("abs(`pageNo`-" + pageNo + ") as diff", new String[] {"diff"}, types ), diff); ---- solution
crit.addOrder(Order.asc("diff"));
crit.setProjection(pl);

I'm facing a similar problem. 我面临着类似的问题。 I'm using Query by Example and I want to sort the results by a custom field. 我正在使用Query by Example,我想通过自定义字段对结果进行排序。 In SQL I would do something like: 在SQL中我会做类似的事情:

select pageNo, abs(pageNo - 434) as diff
from relA
where year = 2009
order by diff

It works fine without the order-by-clause. 没有order-by-clause,它工作正常。 What I got is 我得到的是

Criteria crit = getSession().createCriteria(Entity.class);
crit.add(exampleObject);
ProjectionList pl = Projections.projectionList();
pl.add( Projections.property("id") );
pl.add(Projections.sqlProjection("abs(`pageNo`-"+pageNo+") as diff", new String[] {"diff"}, types ));
crit.setProjection(pl);

But when I add 但是当我补充说

crit.addOrder(Order.asc("diff"));

I get a org.hibernate.QueryException: could not resolve property: diff exception. 我得到一个org.hibernate.QueryException:无法解析属性:diff异常。 Workaround with this does not work either. 解决方法与也不管用。

PS: as I could not find any elaborate documentation on the use of QBE for Hibernate, all the stuff above is mainly trial-and-error approach PS:因为我找不到任何关于QBE用于Hibernate的详细文档,所有上述内容主要是试错法

I do not really think so, what I can find is the word "this." 我真的不这么认为,我能找到的是“这个”。 causes the hibernate not to include any restrictions in its query, which means it got all the records lists. 导致hibernate不在其查询中包含任何限制,这意味着它获得了所有记录列表。 About the hibernate bug that was reported, I can see it's reported as fixed but I totally failed to download the Patch. 关于报告的hibernate错误,我可以看到它被报告为已修复但我完全无法下载补丁。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM