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

Jpa 为什么CascadeType.DETACH在Eclipselink中的FetchType.LAZY的OneToMany关系中不起作用?,jpa,jakarta-ee,eclipselink,jpa-2.0,Jpa,Jakarta Ee,Eclipselink,Jpa 2.0,在带有JPA的标准JEE应用程序中,我有一个主实体a,其中包含一对多个B集合。a实体具有以下形式: @Table(name = "TABLE_A") @Entity public class A implements Serializable { @Id @SequenceGenerator(name = "A_ID_GENERATOR", sequenceName = "SEQ_A", allocationSize = 1, initialValue = 1) @Ge

在带有
JPA
的标准
JEE
应用程序中,我有一个主实体a,其中包含一对多个B集合。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;
     }

}
在具有
@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));

}
@TransactionAttribute(TransactionAttributeType.REQUIRED)
公共void doSomething(字符串密钥){
A A=fetchAByItsBusinessKey(滥用密钥);
listbs=a.getB();
em.a;
//测试B是否被管理
布尔值isManaged=em.contains(bs.get(0));
}
有人能解释为什么
CascadeType.DETACH
FetchType.LAZY
阻止吗?当我将Fetch Type更改为
EAGER
时,分离将传播到B的detail集合

作为引擎,我使用
Eclipse链接


--编辑问题是CascadeType.DETACH未在详细信息集合中传播。所有实体在分离之前都要进行管理和提取。

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


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

好的,我可能错了:您是指此部分并调用getB()是的,在同一个事务中,我获取一个主实体a,调用getB()获取它的类型B的详细实体,然后调用em.detach(a),我希望实体管理器也分离B实体,因为CascadeType。所有你能把你正在使用的
B
也放进去吗?是否存在以及如果存在,那么
A
的注释是什么?我想对此进行测试。检查您的第一个代码段:它有注释
@OneToOne
。然后它有
privateb
但也有返回
b
列表getB()
?你说A包含一对多个B的集合?因此,我认为您需要在代码中编辑一些内容,以使其更易于理解。就像把那些实体放在你测试它们的地方一样。@pirho我编辑了代码,提供了A和B实体,并准确地更正了打字错误。我用@OneToOne测试了OPs代码,只得到了一个
B
,一切都正常,因为它获取了实体。但对于列表来说,情况就是这样。我不知道这是否合适(如果不合适,我将删除),但也许你有话要对我的松散相关的问题说@Chris I编辑代码以提供实体并更正打字错误。不,我在事务内部和分离之前执行Bs的提取,以便按照我的预期正常提取Bs。问题是,如果我在分离当前A后检查Bs,即使我使用
CascadeType,它们仍然处于管理状态。所有的
@IliasStavrakis也将此纳入您的问题中。或者最好是一段循环所有
B
s的代码,然后级联分离仍然失败。这是因为您的调试会话很难为其他人重复执行-刷新前-
bs.get(0)
是否相同?这是克里斯回答的要点。因此,不仅在调试器中,而且在代码中也显示您已填充列表。getBs不会获取Bs。调试器应该显示您拥有的是EclipseLink代理类的一个实例,该类包装集合,仅当确实需要实例时才允许延迟获取该集合。在尝试从集合中访问a B之前,不会获取它,此时代理将填充数据库(或共享缓存)中的引用列表。
@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));

}