In a standard JEE
application with JPA
, I have a master entity A that contains One to Many collection of B. The A Entity has the following form:
@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;
}
}
The Entity B has the following form :
@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;
}
}
In an EJB method with @TransactionAttribute(TransactionAttributeType.REQUIRED)
I retrieve an A from DB and call getB() to fetch the data of B under current A. Then I manually detach the current A with :
em.detach(a);
Before the return of the EJB method, if I test the B instances under current A with em.contains(b)
they are still managed even if I use CascadeType.ALL
.
The transactional method in EJB seems like the following :
@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));
}
Could anyone explain why CascadeType.DETACH
is blocked by FetchType.LAZY
? When I change Fetch Type to EAGER
the detaching is propagated to detail collection of B.
As engine I use Eclipse Link
.
--EDIT The problem is that CascadeType.DETACH is not propagated in detail collections. All entities are managed and fetched before detaching.