Jpa几个@ManyToOne与Cascade

时间:2016-05-12 16:31:34

标签: java spring hibernate jpa cascade

我有三个实体,会话,订单和用户(我的在线电影票项目的一部分)。在我的域模型中,Order保留用户和会话的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吗? 使用会话和用户更新订单时是否存在潜在冲突?

正如您所看到的,我使用fetchType.Lazy,它能保证会话和用户中的订单都是最新的吗?

1 个答案:

答案 0 :(得分:2)

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

// 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即可保留新UserOrder一次通话。如果cascade实体上没有Order注释,则在Order之前保留User会给您一个例外。

参考文献: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或服务层之后。如果您需要访问订单,则需要在选择查询中获取它们:

  

&#34;从Session s join fetch s.orders&#34;

中选择不同的s

编辑:如上所述,默认情况下,此查询会执行sql&#34;内部联接&#34;,如果没有订单,则不会返回任何内容。相反,做

  

&#34;从Session s left join fetch s.orders&#34;

中选择不同的s

这样您就可以获得数据库中的会话。

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