使用Glassfish 4.1,Eclipselink 2.5.1,Oracle 11g。
使用 Oracle代理身份验证持久保持一对多(父子关系)关系时,我们遇到了回滚更改的问题。如果在持久化其中一个子节点时抛出任何异常,则父节点仍将保留到DB(未按预期方式回滚)。我们使用容器管理的JTA实体管理器从无状态EJB保存到DB:
entitymanager.persist(parent);
cascade = CascadeType.ALL
用于父方的关系。
我们的persistence.xml包含<persistence-unit name="admin_war_1.0-SNAPSHOTPU" transaction-type="JTA">
,手头的问题是我们在持久层中唯一的问题(到目前为止,其他一切工作正常)。
父实体类似于:
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;
}
子实体是:
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;
}
以下代码仅供测试:
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);
这是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);
}
}
在通过EJB的所有调用中,我们用
代理entitymanager 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");
上面的行在@AroundInvoke-method
中,因此无论访问什么EJB方法都会运行。
问题仅在代理时出现,而不是在我们省略该部分时。似乎问题与自动提交的jdbc连接有关。我们在Glassfish连接池中尝试了各种参数; relaxAutoCommit = true,AutoCommit = false等,但没有任何改变。
我们如何确保,当孩子坚持失败时父母也会回滚?
答案 0 :(得分:1)
在使用entitymanager和在应用程序服务器中定义的datsource时,我遇到了类似的问题。为了解决这个问题我做了这个:
1- i set transaction-type =&#34; RESOURCE_LOCAL&#34;在persistence.xml中,用于定义持久性单元
2-我使用了非jta-data-source属性,其值为myDatasourceName
我意识到异常的根源是jta!
答案 1 :(得分:0)
快速解决方案似乎是:
em.flush();
这也会让父母回滚 - 不要问我为什么。
请注意,持久化子实体失败时抛出的异常将不同(e.getCause()将不同,以防您向最终用户显示,但它仍将包装在EJBException中。)
另一种解决方案是:
我没有办法让我摆脱它。