2

これには 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 で Projections を作成しようとしています。つまり、 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").as("email")); も試しました。(としての)電子メールをリストに変更しましたが、役に立ちませんでした

Hibernate の List にプロジェクションを作成することは可能ですか?

4

3 に答える 3

1

休止状態はそのような機能を提供していないと思います。これを行うには、Oracle の LISTAGG やMySQLのGROUP_CONCATなどのデータベース固有の関数を使用する必要があります。すべてのメール (文字列) を 1 つの列にグループ化するため、結果は次のようになります。

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();
}
于 2016-09-23T18:53:36.267 に答える
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 などを使用することもできます。

于 2012-08-14T07:29:47.727 に答える