Hibernate中使用查询映射实体

Hibernate中使用查询映射实体,hibernate,hql,hibernate-mapping,Hibernate,Hql,Hibernate Mapping,以桌子为例 sales (id, seller_id, amount, date) 这里是一个视图,它是通过使用查询从销售组中选择卖方id,按卖方id从销售组中求和(金额) total_sales (seller_id, amount) 我想为total sales创建一个实体,但在sql端没有视图 此实体将从查询中构造。我找到的最接近的东西是,但我无法让它工作 即使我定义了加载程序,hibernate也会查找实体的表,如果找不到它,就会给出一个错误。如果我创建的表没有从我定义的命名查询加载

以桌子为例

sales (id, seller_id, amount, date)
这里是一个视图,它是通过使用查询从销售组中选择卖方id,按卖方id从销售组中求和(金额)

total_sales (seller_id, amount)
我想为total sales创建一个实体,但在sql端没有视图

此实体将从查询中构造。我找到的最接近的东西是,但我无法让它工作

即使我定义了加载程序,hibernate也会查找实体的表,如果找不到它,就会给出一个错误。如果我创建的表没有从我定义的命名查询加载实体,Hibernate将生成查询本身


有没有一种方法可以让@Loader工作,或者有没有另一种方法可以将查询映射到实体?

为什么不在查询中使用
new

select new TotalSales(seller_id, count(seller_id))
from sales
group by seller_id
您只需编写一个类TotalSales,其构造函数采用卖方id和整数


编辑:使用标准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
属性。

除了Stefan的答案之外,您还可以使用显式HQL查询

    SELECT seller_id, SUM(amount) FROM sales GROUP BY seller_id
结果自然存储在列表中。如果此数据类型对您不方便, 你可以:

  • 用它们创建新的TotalSale对象(使用Stefan的答案可能更好)
  • 创建一个映射来存储数据(您也可以将其直接嵌入到请求中)

您可以尝试定义自定义加载程序。我从未使用过这个,但它似乎是合理的:

<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>

选择卖家id为{ts.seller\u id},总和(金额)为ts.amount
来自销售
其中seller_id=?
按卖家编号分组
不确定是否需要卖方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;}
}

公共类卖家
{
public int SellerId{get;set;}
公共浮动销售总额{get;set;}
}

因此,它可以访问order by的标准引擎、限制等,我认为这是您希望使用它的原因。

因为我想使用新实体,如
session.createCriteria(TotalSale.class).list()
在我的答案中添加了一部分标准。您给出的答案确实很好,+1,但这并不是我想要的,当我调用session.createCriteria(Sale.class).list()或session.createQuery('from Sale').list()时会发生什么?Hibernate知道如何将一个表映射到一个实体,以便它获取
sales
表中的所有记录。但是因为没有名为
total\u sales
的表,所以当我使用
session.createCriteria(TotalSale.class).list()
时,它不知道如何获取和映射字段。我希望hibernate知道如何将查询映射到实体。就像这里一样:是的,我知道你想这么做。问题是:为什么?你需要解决什么问题?如果通过查询获取实体,通常无法对其进行更新。因此,如果您使用代码中的查询来获取它,这并不重要。但要使实体的自定义加载正常工作,您不会遇到所有这些麻烦。这对
session.createCriteria()
没有任何帮助。实际上,我怀疑在这种情况下是否非常需要createCriteria,因此我提出了其他方法。您将无法使
session.createCriteria(TotalSales.class)正常工作
通过自定义加载程序工作。如果数据库中没有支持对象(表或视图),则不能(也不应该)将其映射为实体。除非“卖方”表存在且未映射到任何其他实体,否则这将无法工作。如果是这样的话,整个观点是没有意义的。事实上,我在帖子中有很多错误,我发布帖子的唯一原因可能是主题发起者得到了一个想法,或者提供了一些他真正需要的信息。否则,斯特凡的回答似乎是正确的