我有一个名为Order的@Entity我有一个字段或一个名为orderEmails的成员变量,如下所示。
@Entity
@Table(name = "order")
public class Order {
@Id
@Column(name = "order_int")
private Long id;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinColumn(name = "order_int", insertable = false, updatable = false)
private List<OrderEmail> orderEmails;
... }
我正在尝试在此订单上创建预测,这意味着我想从Order实体中选择一些特定列,并从OrderEmail实体中选择一列
但是,当我在orderEmails字段上创建投影时。我没有得到完整的电子邮件列表。这就是我想要的。这是我正在尝试的代码
ProjectionList columnList = Projections.projectionList();
...
columnList.add(Projections.property("id").as("id"));
...
columnList.add(Projections.property("orderemails.EmailAddress").as("email"));
注意,我也试过了 columnList.add(Projections.property( “orderemails”)作为( “电子邮件”)。); 并将电子邮件(in as)更改为List,但没有帮助
是否可以在Hibernate中的List上创建投影?
答案 0 :(得分:1)
我猜hibernate没有提供这样的功能。为此,您必须使用数据库特定的函数,如Oracle的LISTAGG或MySQL的GROUP_CONCAT。它会将所有电子邮件(字符串)分组为一个列,结果将是:
ORDER_ID EMAILS
1 nemo@email, dory@email, whale@email
2 spongebob@email, squarepants@email
你可以使用sqlProjection在Hibernate中使用特定于数据库的函数,所以代码看起来像这样:
public List<Map> emailsByOrder(){
Criteria c = session.createCriteria(Order.class,"order");
Criteria critEmail = c.createCriteria("orderEmails", "emails");
String listAgg = "LISTAGG({alias}.EMAIL_ADDRESS_COLUMN_NAME, ', ') WITHIN GROUP(ORDER BY {alias}.EMAIL_ADDRESS_COLUMN_NAME ASC) AS EMAILS";
critEmail.setProjection(Projections.projectionList().add(Projections.groupProperty("order.idOrder").as("ORDER_ID"))
.add(Projections.sqlProjection(listAgg, new String[]{"EMAILS"}, new Type[]{new StringType()})));
c.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
return (List<Map>) c.list();
}
答案 1 :(得分:0)
这不可能像你期望的那样。 Hibernate必须对根实体上的记录进行分组,它只对完整的实体进行记录。
更新
List<Object[]> results = session.createCriteria(Order.class)
.joinAlias("orderEmails", "email")
.setProjection(Projections.projectionList()
.add(Projections.property("id").as("id"))
.add(Projections.property("email.EmailAddress").as("email")))
.list<Object[]>();
Map<int, List<String>> groups = new Hashmap<int, List<String>>();
for (Object[] items : results)
{
if (groups.containsKey((long)items[0]))
groups.get((long)items[0]).add((String)items[1]);
else
groups.add((long)items[0], new List<String>().add((String)items[1]));
}
return groups;
而不是地图,也可以有dtos或类似的东西。
答案 2 :(得分:0)
即使它有点迟了但从来没有太晚, 您可以使用内部列表进行常规投影 在休眠状态下,可以使用以下命令返回一行:
.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)