2013-03-28 49 views
2

我正在使用映射到MS SQLServer中的視圖的hibernate實體。該視圖由從鏈接服務器上的表中選擇的數據組成。我能夠使用JPQL成功查詢此視圖。然而,當我嘗試更新使用entityManager.merge(myEntity所)的觀點,我得到以下錯誤:如何使用JPA/Hibernate設置XACT_ABORT?

com.microsoft.sqlserver.jdbc.SQLServerException: Unable to start a nested transaction for OLE DB provider "MSDAORA" for linked server "DBNAME". A nested transaction was required because the XACT_ABORT option was set to OFF. at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:216) at com.microsoft.sqlserver.jdbc.SQLServerStatement.getNextResult(SQLServerStatement.java:1515) at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.doExecutePreparedStatement(SQLServerPreparedStatement.java:404) at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement$PrepStmtExecCmd.doExecute(SQLServerPreparedStatement.java:350) at com.microsoft.sqlserver.jdbc.TDSCommand.execute(IOBuffer.java:5696) at com.microsoft.sqlserver.jdbc.SQLServerConnection.executeCommand(SQLServerConnection.java:1715) at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeCommand(SQLServerStatement.java:180) at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeStatement(SQLServerStatement.java:155) at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.executeUpdate(SQLServerPreparedStatement.java:314)...

我需要設置XACT_ABORT爲ON,這樣如果出現錯誤的SQLServer可以回滾整個事務。我能夠使用本機查詢解決此問題,但它並不是很理想。

String queryString = """set xact_abort on; update table_name set column1 = :column1, column2 = :column2 where id = :id""" 
    Query query = entityManager.createNativeQuery(queryString) 
    query.setParameter("column1", column1) 
    query.setParameter("column2", column2) 
    query.setParameter("id", id) 
    query.executeUpdate() 

有什麼辦法,我可以配置Hibernate/JPA/JPAVendorAdaptor執行「關於設置XACT_ABORT」爲每一個合併/持續存在,因此我沒有使用本機查詢?

這裏是我的Hibernate配置:

@Resource 
DataSource dataSource 

@Bean 
JpaVendorAdapter vendorAdapter(){ 
    return new HibernateJpaVendorAdapter(database:Database.SQL_SERVER) 
} 

@Bean 
AbstractEntityManagerFactoryBean entityManagerFactory(){ 
    LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(dataSource:dataSource, jpaVendorAdapter:vendorAdapter()) 
    em.setPackagesToScan("com.mycompany.entity") 
    return em 
} 

@Bean 
PlatformTransactionManager transactionManager() { 
    return new JpaTransactionManager(entityManagerFactory:entityManagerFactory().getObject()) 
} 

回答

2

我結束了使用休眠攔截追加 「設置XACT_ABORT ON」 爲每一個INSERT和UPDATE語句。

這裏是我的攔截器:

class XactAbortInterceptor extends EmptyInterceptor{ 
    String onPrepareStatement(String sql) { 
     if(sql.startsWith("insert") || sql.startsWith("update")) 
     sql = "set xact_abort on; " + sql 
     return sql 
    } 
} 

此處,我註冊的攔截器:

@Bean 
AbstractEntityManagerFactoryBean entityManagerFactory(){ 
    LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(dataSource:dataSource, jpaVendorAdapter:vendorAdapter()) 
    em.setPackagesToScan("com.mycompany.entity") 
    em.setJpaPropertyMap(["hibernate.ejb.interceptor": XactAbortInterceptor.class.name]) 
    return em 
} 

我們entityManager.merge(myObject的)或entityManager.persist(myObject的)所有呼叫都將設置XACT_ABORT到上。

希望這可以幫助別人遇到同樣的問題!

0

我必須在persitence.xml文件中註冊攔截器類XactAbortInterceptor