Используйте меньше столбцов в SQL-запросе с помощью проекций гибернации для объекта с отношением ManyToOne

StackOverflow https://stackoverflow.com/questions/1618394

Вопрос

Я пытаюсь создать 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

Я попробовал это с Критериями with (и подкритериями):

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, меньше столбцов?Заранее благодарю.

Это было полезно?

Решение

Прежде всего,

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) через псевдоним и указать проекцию на Главная критерии, использующие указанный псевдоним:

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

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

Другие советы

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top