我正在使用映射到MS SQLServer中的视图的hibernate实体。该视图包含从链接服务器上的表中选择的数据。我能够使用JPQL成功查询此视图。但是,当我尝试使用entityManager.merge(myEntity)更新视图时,出现以下错误:
com.microsoft.sqlserver.jdbc.SQLServerException:无法为链接服务器“DBNAME”的OLE DB提供程序“MSDAORA”启动嵌套事务。由于XACT_ABORT选项设置为OFF,因此需要嵌套事务。 at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:216) 在com.microsoft.sqlserver.jdbc.SQLServerStatement.getNextResult(SQLServerStatement.java:1515) 在com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.doExecutePreparedStatement(SQLServerPreparedStatement.java:404) at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement $ PrepStmtExecCmd.doExecute(SQLServerPreparedStatement.java:350) 在com.microsoft.sqlserver.jdbc.TDSCommand.execute(IOBuffer.java:5696) 在com.microsoft.sqlserver.jdbc.SQLServerConnection.executeCommand(SQLServerConnection.java:1715) 在com.microsoft.sqlserver.jdbc.SQLServerStatement.executeCommand(SQLServerStatement.java:180) 在com.microsoft.sqlserver.jdbc.SQLServerStatement.executeStatement(SQLServerStatement.java:155) 在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为每个合并/持久化执行“set xact_abort on”,这样我就不必使用本机查询了?
这是我的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())
}
答案 0 :(得分:2)
我最终使用一个hibernate拦截器为每个插入和更新语句附加“set xact_abort on”。
这是我的拦截器:
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设置为on。
希望这可以帮助其他人遇到同样的问题!
答案 1 :(得分:0)
我必须在persitence.xml文件中注册拦截器类XactAbortInterceptor