【问题标题】:Jpa several @ManyToOne with CascadeJpa 几个 @ManyToOne 与 Cascade
【发布时间】:2016-09-08 15:02:39
【问题描述】:

我有三个实体,会话、订单和用户(我的在线电影票项目的一部分)。在我的域模型中,Order 保留了 User 和 Session 的 fk。正如您在我的代码中看到的:


@Table(name="Orders")
@Entity

public class Order {
    @ManyToOne
    @JoinColumn(nullable = false)
    private User user;

    @ManyToOne
    private Session session;
    ...
}



@Entity 
@Table(name="Session")

public class Session {
    @OneToMany(fetch=FetchType.LAZY,
               cascade = CascadeType.ALL,
               mappedBy = "session")
    private List<Order> orders = new ArrayList<Order>();
    ...
}



@Table(name="User")
@Entity

public class User {
    @OneToMany(cascade = {  CascadeType.PERSIST,
                            CascadeType.MERGE,
                            CascadeType.REMOVE },
               mappedBy = "user")
    private @Getter Set<Order> orders = new HashSet<>();
    ...
}

我的问题是,我可以在会话和用户中都使用CascadeType.ALL 吗? 使用 Session 和 User 更新 Order 时是否存在潜在冲突?


如您所见,我使用了 fetchType.Lazy,能保证 Session 和 User 中的订单都是最新的吗?

【问题讨论】:

    标签: java spring hibernate jpa cascade


    【解决方案1】:

    问题 1:这是一个很好的问题,但要回答它,您需要了解 owning 实体的概念。带有@ManyToOne 注释的Entity 是关系的所有者。这对开发人员很重要,因为除非在拥有方完成,否则不会保留任何关系,在这种情况下,这意味着设置Order.user。但是,由于您在非拥有的 User 上有 cascade 注释,因此您必须做额外的工作才能使用级联功能:

    // create Order
    Order order = new Order();
    // create User and Set of orders
    User user = new User();
    Set<Order> userOrders = new HashSet<Order>();
    user.setOrders(userOrders);
    userOrders.add(order);
    // and set Order.user
    order.setUser(user);
    // persist with cascade 
    em.persist(user);
    

    请注意,您必须创建一组订单以及设置 Order.user 以保持级联。但是,如果您将 cascade 注释放在拥有实体 Order 上,那么您的工作就会变得简单得多:

    // create User
    User user = new User();
    // create Order
    Order order = new Order();
    // and set Order.user
    order.setUser(user);
    // persist with cascade
    em.persist(order);
    

    现在只需持久化order 将通过一次调用持久化新的User 和Order。在Order 实体上没有cascade 注释,在User 之前持久化Order 会给你一个例外。

    参考:What is the “owning side” in an ORM mapping?、In a bidirectional JPA OneToMany/ManyToOne association, what is meant by “the inverse side of the association”?

    问题 2:FetchType.LAZY 表示您必须通过特定查询来获取孩子,所以如果我理解您的问题,答案是否定的,它不能保证任何事情。使用FetchType.LAZY,当您获得Session 时,您将无法在实体分离时访问Session.orders,通常是在您离开会话Bean 或服务层之后。如果您需要访问订单,则需要在选择查询中获取它们:

    "select distinct s from Session s join fetch s.orders"

    编辑:如前所述,默认情况下,此查询执行 sql“内部联接”,如果没有订单,它将不返回任何内容。相反,做

    "select distinct s from Session s left join fetch s.orders"

    以便您始终获得数据库中的会话。

    参考:Difference between FetchType LAZY and EAGER in Java Persistence API?

    【讨论】:

    • 谢谢,正是我要找的!
    • "select distinct s from Session s join fetch s.orders",但如果 s.orders 为空,此查询将返回 null。如果我在数据库中有一个空订单的会话,我该如何插入一个订单?
    猜你喜欢
    • 1970-01-01
    • 2012-03-31
    • 1970-01-01
    • 1970-01-01
    • 2018-11-08
    • 2019-03-31
    • 1970-01-01
    • 2016-11-14
    • 1970-01-01
    相关资源
    最近更新 更多