Mapa de la entidad mediante consulta en Hibernate
-
05-07-2019 - |
Pregunta
considere la tabla
sales (id, seller_id, amount, date)
y aquí hay una vista que se genera a partir de ventas
utilizando la consulta SELECCIONAR ID de vendedor, SUMA (cantidad) DE las ventas GRUPO POR vendedor_cosa
total_sales (seller_id, amount)
Quiero crear una entidad para ventas totales pero sin la vista en el lado del SQL.
Esta entidad se construirá a partir de una consulta. Lo más cercano que encontré es this , pero no pude hacerlo funcionar.
Incluso si defino el cargador, hibernación busca la tabla de la entidad y da un error si no puede encontrarla. Si creo la tabla, no se carga la entidad de la consulta nombrada que definí, Hibernate genera la consulta en sí misma.
¿Hay alguna forma de hacer que @Loader funcione o hay otra forma en la que puedo asignar una consulta a una entidad?
Solución
¿Por qué no usas new
en la consulta?
select new TotalSales(seller_id, count(seller_id))
from sales
group by seller_id
Simplemente escribes una clase TotalSales con un constructor que toma el seller_id y un entero.
Editar : cuando utilice los criterios API, puede usar AliasToBeanResultTransformer
(consulte documentos API ). Copia cada nombre de alias a una propiedad del mismo nombre.
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();
Luego, su TotalSales
necesita una propiedad de SellerId
y Count
.
Otros consejos
Además de la respuesta de Stefan, también puede usar una consulta HQL explícita para
SELECT seller_id, SUM(amount) FROM sales GROUP BY seller_id
El resultado se almacena naturalmente en la Lista. Si este tipo de datos no es conveniente para usted, usted podría:
- crear nuevos objetos de TotalSale con ellos (probablemente sería mejor usar la respuesta de Stefan)
- cree un mapa para almacenar los datos (también puede incrustarlo directamente en la solicitud).
Puede intentar definir un cargador personalizado. Nunca utilicé esto, pero parece razonable:
<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>
No estoy seguro si el filtro en el seller_id es necesario.
Hace referencia a esta consulta nombrada en una asignación de clase:
<class name="TotalSale">
<id name="seller_id">
<generator class="increment"/>
</id>
<property name="seller_id" />
<property name="amount" />
<loader query-ref="totalSale"/>
</class>
Hay más detalles en el manual .
Alternativamente, puede usar directamente una consulta de nombre del código, de esta manera no necesita un mapeo de TotalSale y no tiene que escribir la consulta en el código. Las consultas con nombre también pueden devolver objetos. Consulte detalles sobre consultas nombradas en la documentación.
Si realmente desea una entidad específica solo para este trabajo, puede usar una 'fórmula' en una propiedad personalizada
<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;}
}
como tal, es accesible al motor de Criterios para pedidos, restricciones, etc., que creo que es la razón por la que desea utilizarlo.