控制什么是懒惰(或急切)加载

时间:2014-04-01 06:59:17

标签: java jpa-2.0

我目前的结构如下(伪代码):

public class Order
{
    @OneToMany(targetEntity = Orderline.class, fetch = FetchType.LAZY)
    private List<Orderline> orderlines;

    private Client client;
}

public class Orderline
{
    @ManyToOne(mappedBy = 'orderlines')
    private Order order;

    private Client client;
}

public class Client
{
    // your usual Client class, its contents aren't important for the question
}

假设我可以拥有ID为123的订单,该订单属于客户端X.我也可以拥有ID为123的订单,该订单属于客户端Y.当延迟加载(或急切加载,就此而言)时,怎么能我知道当我从数据库中获取客户端X的ID为123的订单时,我不能从客户端Y获取订单线?如果JPA仅检查订单行侧的外键,是否有办法在延迟(或急切)加载时为客户端添加检查?

我想在不使用Hibernate或Eclipselink这样的特定实现的情况下解决这个问题,这样我就可以在必要时轻松切换实现。

1 个答案:

答案 0 :(得分:2)

如果您只是使用&#34; ID(123)&#34;您选择的ID可能是不够的。作为订单实体的ID。

在JPA中,每个实体都应具有唯一标识符。如果有两个订单(一个用于X,一个用于Y)使用相同的ID,那么一切都搞砸了。

我个人的建议是在整个系统中使ID唯一。如果您希望每个客户端使用某种序列号,请将其保留为另一个字段。

当然,还有另一种选择,即将客户ID和订单ID作为复合键。

简而言之,请确保您选择的ID可以唯一地标识实体(通常表示DB中的一行)。

示例(第一种方法,唯一ID)

public class Order
{
    @Id
    private Long id;

    @OneToMany(targetEntity = Orderline.class, fetch = FetchType.LAZY)
    private List<Orderline> orderlines;

    private Client client;

    private Long orderSequence;  // unique within a client
}

public class Orderline
{
    @Id
    private Long id;   // unique ID of order line

    @ManyToOne(mappedBy = 'orderlines')
    private Order order;

    // not necessary, as you can access through orderLine.order.client
    // private Client client;
}

第二种方法(复合键):

public class Order
{
    @EmbeddedId
    private OrderId id;

    @ManyToOne
    @JoinColumn(insertable=false, updatable=false)
    private Client client;

    @Column(insertable=false, updatable=false)
    private Long orderSequence;  // unique within a client

    @OneToMany(targetEntity = Orderline.class, fetch = FetchType.LAZY)
    private List<Orderline> orderlines;
}

@Embeddable
public class OrderId {
    Long clientId;
    Long orderSequence;
}