Объект отображения, использующий запрос в режиме гибернации
-
05-07-2019 - |
Вопрос
рассмотрим таблицу
sales (id, seller_id, amount, date)
и вот представление, которое генерируется из sales
использование запроса SELECT seller_id, SUM(amount) FROM sales GROUP BY seller_id
total_sales (seller_id, amount)
Я хочу создать объект для общих продаж, но без представления на стороне sql.
Этот объект будет создан на основе запроса.Самое близкое, что я нашел, это это, но я не смог заставить это сработать.
Даже если я определяю загрузчик, hibernate ищет таблицу объекта и выдает ошибку, если не может ее найти.Если я создаю таблицу, она не загружает объект из определенного мной именованного запроса, Hibernate генерирует сам запрос.
Есть ли способ заставить @Loader работать или есть другой способ, которым я могу сопоставить запрос с сущностью?
Решение
Почему бы вам просто не использовать new
в запросе?
select new TotalSales(seller_id, count(seller_id))
from sales
group by seller_id
Вы просто пишете класс TotalSales с конструктором, принимающим seller_id и целое число.
<Ч> Изменить . При использовании API критериев вы можете использовать AliasToBeanResultTransformer
(см. документы API ). Он копирует каждое псевдоним в одноименное свойство.
List list = s.createCriteria(Sales.class)
.setProjection(Projections.projectionList()
.add( Projections.property("id"), "SellerId" )
.add( Projections.rowCount("id"), "Count" ) )
.setResultTransformer(
new AliasToBeanResultTransformer(TotalSales.class) )
.list();
Тогда вашему TotalSales
требуется свойство SellerId
и Count
.
Другие советы
В дополнение к ответу Стефана, вы также могли бы использовать явный запрос HQL для
SELECT seller_id, SUM(amount) FROM sales GROUP BY seller_id
Результат, естественно, сохраняется в List.Если этот тип данных вам не подходит, вы могли бы:
- создайте с ними новые объекты TotalSale (вероятно, было бы лучше использовать ответ Стефана)
- создайте карту для хранения данных (вы также можете встроить это непосредственно в запрос).
Вы можете попытаться определить настроенный загрузчик. Я никогда не использовал это, но это кажется разумным:
<sql-query name="totalSale">
<return alias="ts" class="TotalSale" />
SELECT seller_id as {ts.seller_id}, SUM(amount) as ts.amount
FROM sales
WHERE seller_id = ?
GROUP BY seller_id
</sql-query>
Не уверен, нужен ли фильтр для seller_id.
Вы ссылаетесь на этот именованный запрос в отображении класса:
<class name="TotalSale">
<id name="seller_id">
<generator class="increment"/>
</id>
<property name="seller_id" />
<property name="amount" />
<loader query-ref="totalSale"/>
</class>
более подробную информацию можно найти в руководство .
Кроме того, вы можете напрямую использовать запрос имени из кода, таким образом вам не нужно отображать TotalSale и не нужно писать запрос в коде. Именованные запросы также могут возвращать объекты. См. сведения об именованных запросах в документации.
если вы действительно хотите конкретную сущность только для этой работы, вы можете использовать «формулу» в пользовательском свойстве
<class name="SellerSales" table="Sales" lazy="true">
<id name="SellerId" column="SellerId" type="int">
<generator class="native" />
</id>
<property name="SalesSum" type="float" update="false" insert="false"
formula="select SUM(sal.ammount) from sales sal where sal.seller_id = SellerId)" />
</class>
public class SellerSales
{
public int SellerId {get; set;}
public float SalesSum {get; set;}
}
как таковой, он доступен для механизма Criteria для упорядочивания, ограничений и т. д., по-моему, является причиной, по которой вы хотите его использовать.