4

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

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

select description, weight from Dog;

嗨,我有这个实体:

@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;
}

我的目标是拥有这个:

select description, weight, owner.name from Dog

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

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.

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

4

2 回答 2

4

首先,

select description, weight, owner.name from Dog

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

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

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

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

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

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

于 2009-10-24T18:49:31.990 回答
0

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

于 2018-09-06T12:54:38.150 回答