2015-10-07 50 views
1

使用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等,但沒有任何改變。

我們如何確保父母也能回滾,如果堅持孩子失敗?

+1

您尚未顯示事務分界,數據源定義或異常本身,因此我們無法看到問題所在。我的猜測是,您還沒有在glassfish中設置JTA數據源,因此EclipseLink正在通過事務外部的連接進行寫入,從而導致每個語句都被自動提交。 – Chris

+0

非常感謝克里斯 - 你是對的,爲了簡潔,我省略了很多。劃分是通過在STSB中使用CMT給出的,不是嗎?對不起,我沒有明確說出。 GF中的JTA數據源有什麼特別需要(我們有一個「標準」數據源/連接池定義)?但是,似乎問題出在Oracle代理認證上,這是我爲簡單起見而忽略的另一件事。正如你所說,這似乎導致了交易之外的聯繫。如果確認,將刪除問題。感謝您再次發表評論 –

回答

0

快速的解決方案似乎是:

  • 完EJB的方法與em.flush();

這會讓母捲回過 - 不要問我爲什麼。

請注意,持久化子實體失敗時引發的異常將會有所不同(如果向最終用戶展示,e.getCause()將會不同,但是它仍將包裝在EJBException中)。

另一種解決方案是:

  • 使用RESOURCE_LOCAL和寫在其它答案非JTA數據源。您必須在EJB中注入EntityManagerFactory並自己執行事務處理。

我沒有找到一種方法來配置我。

1

我在使用entitymanager和應用程序服務器中定義的datasource時遇到了類似的問題。用於解決該問題我這樣做:

1-我設置在persistence.xml中,並且用於限定持久單元交易類型=「RESOURCE_LOCAL」

2-我用非JTA數據源屬性與myDatasourceName的值

我意識到異常的根是jta!

+0

您是否也在使用Oracle代理身份驗證@Abbas? –