Reputation: 4345
Using Glassfish 4.1, Eclipselink 2.5.1, Oracle 11g.
We're having a problem rolling back changes when persisting a one-to-many (parent-children) relationship using Oracle proxy authentication. If any exception is thrown when persisting one of the children, the parent will still be persisted to the DB (not rolled back as expected). We save to DB from a stateless EJB with a container-managed JTA entitymanager with:
entitymanager.persist(parent);
cascade = CascadeType.ALL
is used on the relationship on the parent side.
Our persistence.xml contains <persistence-unit name="admin_war_1.0-SNAPSHOTPU" transaction-type="JTA">
and the problem at hand is the only one we have in the persistence layer (so far, everything else is working fine).
The parent entity is something like:
public class KornstoranalyseStd implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Basic(optional = false)
@Column(name = "KORNSTORANALYSE_STD_ID", nullable = false)
private Integer kornstoranalyseStdId;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "kornstoranalyseStd", fetch = FetchType.EAGER)
@OrderBy("maskestoerrelse DESC")
private Collection<KornstoranalyseStdSigte> kornstoranalyseStdSigteCollection;
}
And the child entity is:
public class KornstoranalyseStdSigte implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Basic(optional = false)
@Column(name = "KORNSTORANALYSE_STD_SIGTE_ID", nullable = false)
private Integer kornstoranalyseStdSigteId;
@Basic(optional = false)
@NotNull
@Column(name = "MASKESTOERRELSE", nullable = false, precision = 12, scale = 8)
private BigDecimal maskestoerrelse;
@JoinColumn(name = "KORNSTORANALYSE_STD_ID", referencedColumnName = "KORNSTORANALYSE_STD_ID", nullable = false)
@ManyToOne(optional = false, fetch = FetchType.EAGER)
private KornstoranalyseStd kornstoranalyseStd;
}
The following code is for testing only:
KornstoranalyseStd parent = new KornstoranalyseStd();
parent.setKornstoranalyseStdId(1);
List<KornstoranalyseStdSigte> children = new ArrayList<>();
KornstoranalyseStdSigte child = new KornstoranalyseStdSigte();
child.setKornstoranalyseStdSigteId(1);
child.setMaskestoerrelse(new BigDecimal(11));
child.setKornstoranalyseStd(parent);
children.add(child);
parent.setKornstoranalyseStdSigteCollection(children);
getEjbFacade().create(parent);
This is the STSB:
@Stateless
public class KornstoranalyseStdFacade {
@PersistenceContext(unitName = "admin_war_1.0-SNAPSHOTPU")
private EntityManager em;
private EntityManager getEntityManager() {
return em;
}
public void create(KornstoranalyseStd entity) {
getEntityManager().persist(entity);
}
}
In all calls through the EJB, we proxy the entitymanager with
getEntityManager().setProperty("eclipselink.oracle.proxy-type", 1);
getEntityManager().setProperty("PROXY_USER_NAME", loginBean.getUsername());
getEntityManager().setProperty("PROXY_USER_PASSWORD", loginBean.getPassword());
getEntityManager().setProperty("eclipselink.jdbc.exclusive-connection.mode", "Always");
getEntityManager().setProperty("eclipselink.jdbc.exclusive-connection.is-lazy", "true");
The above lines are in an @AroundInvoke-method
, and will therefore be run no matter what EJB-method is accessed.
The problem is only present when proxying, not if we omit that part. It seems the problem is related to the jdbc-connections being autocommitted. We've tried all kinds of parameters in the Glassfish Connection pool; relaxAutoCommit=true, AutoCommit=false etc., but nothing has changed anything.
How can we ensure, that the parent is also rolled back, when persisting a child fails?
Upvotes: 1
Views: 162
Reputation: 4345
The quick solution seems to be:
em.flush();
That'll make the parent roll back too - don't ask me why.
Note that the exception thrown when persisting a child entity fails will be different (e.getCause() will be different, in case you show to the enduser, but it will still be wrapped in an EJBException).
Another solution is:
I didn't find a way to configure me out of it.
Upvotes: 0
Reputation: 81
I had similar problem when using entitymanager with datsource defined in application server. for solving the problem i did this:
1- i set transaction-type="RESOURCE_LOCAL" in persistence.xml and for defining persistence-unit
2- I used non-jta-data-source property with value of myDatasourceName
i realized that root of exception is jta!
Upvotes: 1