java 通过 Hibernate Projections on Entity with ManyToOne 关系在 SQL 查询中使用更少的列

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1618394/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 17:18:07  来源:igfitidea点击:

Use fewer columns on SQL query through Hibernate Projections on Entity with ManyToOne relation

javasqlhibernatecriteriaprojection

提问by Awi

I'm trying to build a smaller SQL, to avoid the "select * from A" that is being build by default for hibernate Criteria.

我正在尝试构建一个较小的 SQL,以避免默认情况下为休眠标准构建的“select * from A”。

If I use simple fields (no relation), through "Transformers", I have can manage to have this SQL:

如果我使用简单的字段(没有关系),通过“变形金刚”,我可以设法拥有这个 SQL:

select description, weight from Dog;

Hi, I have this Entity:

嗨,我有这个实体:

@Entity
public class Dog
{
   Long id;
   String description;
   Double weight;
   @ManyToOne(fetch = FetchType.LAZY)
   @JoinColumn(name = "person_id", nullable = false)
   Person owner;
}

@Entity
public class Person
{
   Long id;
   String name;
   Double height;
   Date birthDate;
}

My goal is to have this:

我的目标是拥有这个:

select description, weight, owner.name from Dog

I tried this with with Criteria (and subcriteria):

我用标准(和子标准)尝试了这个:

Criteria dogCriteria = sess.createCriteria(Dog.class);
ProjectionList proList = Projections.projectionList();
proList.add(Projections.property("description"), description);
proList.add(Projections.property("weight"), weigth);
dogCriteria.setProjection(proList);

Criteria personCriteria = dogCriteria.createCriteria("owner");
ProjectionList ownerProList = Projections.projectionList();
ownerProList.add(Projections.property("name"), description);    
dogCriteria.setProjection(ownerProList);  //After this line,  debugger shows that the
                                          //projection on dogCriteria gets overriden
                                          //and the query fails, because "name" is
                                          //not a field of Dog entity.

How should I use Projections, to get a smaller SQL, less columns ? Thanks in advance.

我应该如何使用投影来获得更小的 SQL,更少的列?提前致谢。

采纳答案by ChssPly76

First of all,

首先,

select description, weight, owner.name from Dog

is not valid SQL. It would have to be something like

不是有效的 SQL。它必须是这样的

select description, weight, Person.name
 from Dog join Person on Dog.person_id = Person.id

instead. Secondly, why? While it's possible to do what you want (see below), it's extremely verbose to do so via Criteria API and you gain nothing to show for it. Savings on data transfer for a couple of columns are negligible unless said columns are huge blobs or you're selecting hundreds of thousands of records. In either case there are better ways to deal with this issue.

反而。其次,为什么?虽然可以做你想做的事(见下文),但通过 Criteria API 这样做是非常冗长的,而且你没有什么可展示的。几列的数据传输节省可以忽略不计,除非所述列是巨大的 blob,或者您要选择数十万条记录。无论哪种情况,都有更好的方法来处理这个问题。

Anywho, to do what you want for criteria, you need to join linked table (Person) via alias and specify projection on maincriteria using said alias:

Anywho,要根据您的条件执行您想要的操作,您需要通过别名加入链接表 (Person) 并使用所述别名指定对主要条件的投影:

Criteria criteria = session.createCriteria(Dog.class, "dog")
 .createAlias("owner", "own")
 .setProjection( Projections.projectionList()
   .add(Projections.property("dog.description"))
   .add(Projections.property("dog.weight"))
   .add(Projections.property("own.name"))
 );

There's a description and an example of the above in Criteria Projections documentation. Keep in mind that, when executed, the above criteria would return a list of object arrays. You'll need to specify a ResultTransformerin order to have results converted into actual objects.

Criteria Projections 文档中有对上述内容的描述和示例。请记住,在执行时,上述条件将返回一个对象数组列表。您需要指定一个ResultTransformer以便将结果转换为实际对象。

回答by Christian Lischnig

I didn't tried it yet by myself, but I think you can also use another constructor in your Entity (Pojo) and pass the columns there. See https://www.thoughts-on-java.org/hibernate-best-practices/chapter "1.2 Pojo" for a detailed instruction. Altough for me it's not yet clear if this also works for ManyToOne relationships too. I will have a try.

我自己还没有尝试过,但我认为你也可以在你的实体(Pojo)中使用另一个构造函数并在那里传递列。有关详细说明,请参阅https://www.thoughts-on-java.org/hibernate-best-practices/章节“1.2 Pojo”。虽然对我来说尚不清楚这是否也适用于多对一关系。我会试试的。