【问题标题】:Mapping a Map or List multiplies parent result映射 Map 或 List 乘以父结果
【发布时间】:2012-11-26 10:38:59
【问题描述】:

我在映射包含列表(或地图)的实体时遇到问题。我已经尝试了各种注释组合,但“最好”的两种变体都有这种行为。例如,如果父对象有 3 个子对象,则父对象被检索 3 次。

我的代码

在我的例子中,我有一个 UserOrder 对象,其中包含一对带有计数的 Products。数据结构是这样的

@Entity
public class UserOrder{ 
    /* 
     * VARIATION 1 
     * I did actually vary some of these annotions, not all are necessary. 
     * I believe the @CollectionTable is the key here
     */
    @ElementCollection(fetch = FetchType.EAGER)
    @CollectionTable
    @Column
    @Embedded
    private List<ProductCount> products;

    /*
     * VARIATION 2
     */
    @ElementCollection(fetch = FetchType.EAGER)
    private Map<Product, Integer> products = new HashMap<Product, Integer>();

    // get/set
    // ...
}

@Embeddable
/* Only used in variation 1 */
public class ProductCount{
    @OneToOne
    private Product product;

    @Column
    private Integer amount;

    // get/set
}

@Entity
public class Product
{
    // ...
}

然后使用类似这样的方式调用和显示(这是用于变体 2)

<!-- Called via DAO/Service layers
List<Order> orders = getSession().createCriteria(UserOrder.class).list();
-->
<c:forEach items="${orders}" var="order">
    <fmt:formatDate value="${order.time}" type="both" />
    <c:forEach items="${order.products}" var="pc">
        ${pc.value} x ${pc.key.name}
    </c:forEach>
</c:forEach>

为了记录,我使用的是 Spring (3.1)、Hibernate (3.5),我想继续使用 JPA 注释。

问题

当我检索订单时,我会为其中包含的每个产品获得一个 UserOrder-object,而不是为我存储的每个订单获得一个 UserOrder。所以我在我的列表中得到了重复,所有这些都包含它包含的产品的完整信息。没有产品的订单也包括在内

  • 订单 1 -- 有 2 个产品
    • 1 x DogToy1
    • 3 x 猫玩具 1
  • 订单 1 -- 有 2 个产品
    • 1 x DogToy1
    • 3 x 猫玩具 1
  • 订单 2 -- 有 1 个产品
    • 3 x 猫玩具 1
  • 订单 3 -- 有 0 个产品

如何让 Hibernate 向我返回一 (1) 个 UserOrder 而不是每个产品一个?或者,我是否采取了正确的方法来建模这个结构?

【问题讨论】:

    标签: java spring hibernate jpa annotations


    【解决方案1】:

    选项:

    • 延迟加载子集合(应该有批量加载延迟加载集合的选项)
    • 在查询上使用 DistinctRootentityResulttransformer

    【讨论】:

    • 延迟加载给我关闭会话带来了麻烦,但我也不认为它在语义上是正确的,因为当我显示一个订单时我通常需要订单的内容。我会研究一下 Transformer,但我不想给它带来额外的复杂性
    • 好吧,其实加变压器也不难。我会将我的实现添加到您的答案中并接受它
    • 有延迟加载并不意味着它总是延迟加载,您可以在查询中指定获取路径以不同方式加载每个用例的关联
    • Joost 评论:// Create criteria Criteria c = sessionFactory.getCurrentSession().createCriteria(UserOrder.class); // Make sure we get only one root entity c.setResultTransformer(DistinctRootEntityResultTransformer.INSTANCE); // Return a list return c.list();
    猜你喜欢
    • 1970-01-01
    • 2019-11-27
    • 1970-01-01
    • 2017-12-10
    • 2017-11-25
    • 2013-01-14
    • 2012-04-04
    • 1970-01-01
    • 2018-12-07
    相关资源
    最近更新 更多