为什么CascadeType.DETACH在Eclipselink中的FetchType.LAZY的OneToMany关系中不起作用?

时间:2017-11-09 09:50:46

标签: jpa java-ee eclipselink jpa-2.0

JEE的标准JPA应用程序中,我有一个包含一对多B集合的主实体A.A实体具有以下形式:

@Table(name = "TABLE_A")
@Entity
public class A implements Serializable {

    @Id
    @SequenceGenerator(name = "A_ID_GENERATOR", sequenceName = "SEQ_A", allocationSize = 1, initialValue = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "A_ID_GENERATOR")
    @Column(unique = true, nullable = false, precision = 16)
    private Long id;

    @OneToMany(cascade = CascadeType.ALL , fetch = FetchType.LAZY  , mappedBy = "a")
     private List<B> bCollection;
     public List<B> getB() {
        return this.bCollection;
     }

     public void setB(List<B> bCollection) {
        this.bCollection = bCollection;
     }

     public Long getId() {
         return id;
     }

     public void setId(Long id) {
         this.id = id;
     }

}

实体B具有以下形式:

@Table(name = "TABLE_B")
@Entity
public class B implements Serializable {

    @Id
    @SequenceGenerator(name = "B_ID_GENERATOR", sequenceName = "SEQ_B", allocationSize = 1, initialValue = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "B_ID_GENERATOR")
    @Column(unique = true, nullable = false, precision = 16)
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "A_FK")
    private A a;

    public Long getId() {
        return this.id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public A getA() {
        return this.a;
    }

    public void setA(A a) {
        this.a = a;
    }

}

在带有@TransactionAttribute(TransactionAttributeType.REQUIRED)的EJB方法中,我从DB检索A并调用getB()以获取当前A下的B的数据。然后我手动分离当前的A:

em.detach(a);

在返回EJB方法之前,如果我使用em.contains(b)测试当前A下的B实例,即使我使用CascadeType.ALL,它们仍然会被管理。

EJB中的事务方法如下所示:

@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void doSomething(String aBusinessKey) {

    A a = fetchAByItsBusinessKey(aBusinessKey);
    List<B> bs = a.getB();

    em.detach(a);

    //Test if Bs are managed
    boolean isManaged = em.contains(bs.get(0));

}

有人可以解释为什么CascadeType.DETACHFetchType.LAZY阻止了吗?当我将Fetch Type更改为EAGER时,分离将传播到B的详细信息集合。

作为引擎我使用Eclipse Link

- 编辑问题是CascadeType.DETACH不会在详细信息集合中传播。在分离之前管理和获取所有实体。

1 个答案:

答案 0 :(得分:1)

仅分离获取的属性和关系的级联,并且在分离A之后获取B列表.getB仅返回提供者的集合实现 - 实际集合的代理,并且不获取结果。只有访问此集合(例如调用它的大小)才会触发获取。

在其他提供程序上,这会导致异常,但只要上下文仍然可用,EclipseLink就允许获取延迟关系。如果实体未被序列化并且EMF仍处于打开状态,为了保持对象标识,EclipseLink将使用读取实体的EntityManager来获取您的集合,从而导致在该EntityManager中管理结果。