Используйте меньше столбцов в запросе SQL через Hibernate Projection on Entity с отношением ManyToOne - PullRequest
4 голосов
/ 24 октября 2009

Я пытаюсь создать меньший SQL, чтобы избежать «выбора * из 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.

Как использовать проекции, чтобы получить меньший SQL, меньше столбцов? Заранее спасибо.

Ответы [ 2 ]

4 голосов
/ 24 октября 2009

Прежде всего

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, и вы ничего не можете показать за это. Экономия на передаче данных для пары столбцов незначительна, если только указанные столбцы не являются большими каплями или вы выбираете сотни тысяч записей. В любом случае есть более эффективные способы решения этой проблемы.

В любом случае, чтобы сделать то, что вы хотите для критериев, вам нужно присоединиться к связанной таблице (Person) через псевдоним и указать проекцию для main критериев, используя указанный псевдоним:

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

Описание и пример вышесказанного можно найти в Документация по критериям проекции . Имейте в виду, что при выполнении вышеприведенные критерии будут возвращать список массивов объектов. Вам нужно будет указать ResultTransformer , чтобы результаты преобразовывались в реальные объекты.

0 голосов
/ 06 сентября 2018

Я еще не пробовал сам, но я думаю, что вы также можете использовать другой конструктор в вашей сущности (Pojo) и передавать туда столбцы. См. https://www.thoughts -on-java.org / hibernate-best-Practices / главу "1.2 Pojo" для получения подробной инструкции. Хотя для меня пока не ясно, работает ли это и для отношений ManyToOne. Я попробую.

...