使用Glassfish 4.1,Eclipselink 2.5.1,Oracle 11g。Oracle代理認證:整個事務的回滾
當使用Oracle代理身份驗證來保持一對多(父 - 子)關係時,我們遇到了回滾更改的問題。如果在保留其中一個子項時引發任何異常,則父項仍將保留到數據庫(不按預期方式回滾)。我們保存到數據庫從一個無狀態EJB與容器管理的JTA EntityManager的有:
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,我們代理與
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
EntityManager的,因此,將被無論什麼EJB的方法訪問運行。
該問題只在代理時才存在,而不是如果我們忽略該部分。看來問題與jdbc連接是自動提交有關。我們已經嘗試了Glassfish Connection池中的各種參數; relaxAutoCommit = true,AutoCommit = false等,但沒有任何改變。
我們如何確保父母也能回滾,如果堅持孩子失敗?
您尚未顯示事務分界,數據源定義或異常本身,因此我們無法看到問題所在。我的猜測是,您還沒有在glassfish中設置JTA數據源,因此EclipseLink正在通過事務外部的連接進行寫入,從而導致每個語句都被自動提交。 – Chris
非常感謝克里斯 - 你是對的,爲了簡潔,我省略了很多。劃分是通過在STSB中使用CMT給出的,不是嗎?對不起,我沒有明確說出。 GF中的JTA數據源有什麼特別需要(我們有一個「標準」數據源/連接池定義)?但是,似乎問題出在Oracle代理認證上,這是我爲簡單起見而忽略的另一件事。正如你所說,這似乎導致了交易之外的聯繫。如果確認,將刪除問題。感謝您再次發表評論 –