如果发生错误,我在回滚EJB事务时遇到了问题。以下情况:我有一个无状态的EJB,它试图在一个新事务中持久化3个对象。我使用HiberNate 5.2作为JPA提供者,使用Payara4.1.2.173作为应用程序服务器。
@Stateless
public class MyEJB {
@PersistenceContext(unitName = "myUnit")
private EntityManager entityManager;
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void persistData() {
this.log.info("Method start.");
// valid
MyObj obj1 = new MyObj();
obj1.setField1("v1");
obj1.setField2("v2");
entityManager.persist(obj1);
this.log.info("Persisted obj1");
// valid
MyObj obj2 = new MyObj();
obj2.setField1("v1");
obj2.setField2("v2");
entityManager.persist(obj2);
this.log.info("Persisted obj2");
// failure
MyObj obj3 = new MyObj();
obj3.setField1("v1");
obj3.setField2("FAILURE");
entityManager.persist(obj3);
this.log.info("Persisted obj3");
this.log.info("Method finished.");
}
}
由于field2上的无效值,obj3的持久性应该会失败。当从我的ejb外部调用这个方法时(例如,从另一个EJB,一个消息驱动bean,通过rest,...)执行hibernate insert语句时,日志文件中出现< code > persistence exception 。所以obj3不会持久存储在数据库中。日志文件还说“事务标记为回滚”。但是当我查看数据库时,obj1和obj2是持久的。因此,我认为回滚没有完成或不完整。我还尝试使用< code>@Transactional注释,但是行为没有变化。我也不能使用try-catch,因为在对象创建和< code>persist(obj)调用时不会出现异常。在< code>persistence.xml中,我将属性< code > hibernate . connection . auto commit 设置为< code>false。
我的persistence.xml是:
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
version="2.1">
<persistence-unit name="myUnit" transaction-type="JTA">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<jta-data-source>jdbc/name</jta-data-source>
<properties>
<property name="hibernate.transaction.jta.platform" value="org.hibernate.service.jta.platform.internal.SunOneJtaPlatform"/>
<property name = "hibernate.show_sql" value = "false" />
<property name="hibernate.dialect" value="org.hibernate.dialect.Oracle12cDialect" />
<property name="hibernate.connection.autocommit" value="false" />
</properties>
</persistence-unit>
</persistence>
数据库连接在 Payaras 域中的池定义中完成.xml:
<resources>
<jdbc-resource pool-name="pool-name" jndi-name="jdbc/name"></jdbc-resource>
<jdbc-connection-pool match-connections="true" connection-leak-reclaim="true" driver-classname="" statement-leak-reclaim="true"
connection-creation-retry-attempts="3" associate-with-thread="true" validation-table-name="DUAL"
description="" validation-classname="" res-type="javax.sql.XADataSource" max-wait-time-in-millis="120000"
fail-all-connections="true" allow-non-component-callers="true" datasource-classname="oracle.jdbc.xa.client.OracleXADataSource"
is-connection-validation-required="true" transaction-isolation-level="read-committed" validate-atmost-once-period-in-seconds="30"
lazy-connection-enlistment="true" connection-creation-retry-interval-in-seconds="7" max-pool-size="45"
connection-leak-timeout-in-seconds="1800" statement-leak-timeout-in-seconds="900" steady-pool-size="10"
name="pool-name" statement-timeout-in-seconds="900" sql-trace-listeners="" init-sql="">
<property name="Password" value="password"></property>
<property name="User" value="user"></property>
<property name="URL" value="jdbc:oracle:thin:@//localhost:1521/db-identifier"></property>
</jdbc-connection-pool>
</resources>
我失败的堆栈跟踪显示在下面的段落中。正如您所看到的,创建了3个插入语句。持久数据()
代码完成后,HiberNate尝试执行这些语句,并在目标3插入时发生失败并启动回滚。但是目标1和目标2随后被持久化在数据库中。为了更好地理解,我添加了一些日志语句。
[2018-09-02T17:41:51.111+0200] [Payara 4.1] [INFO] [] [...] [tid: _ThreadID=28 _ThreadName=http-thread-pool::http-listener-1(2)] [timeMillis: 1535903502294] [levelValue: 800] [[
Method start.]]
[2018-09-02T17:41:51.222+0200] [Payara 4.1] [INFO] [] [...] [tid: _ThreadID=28 _ThreadName=http-thread-pool::http-listener-1(2)] [timeMillis: 1535903502430] [levelValue: 800] [[
Persisted obj1]]
[2018-09-02T17:41:51.333+0200] [Payara 4.1] [INFO] [] [...] [tid: _ThreadID=28 _ThreadName=http-thread-pool::http-listener-1(2)] [timeMillis: 1535903502431] [levelValue: 800] [[
Persisted obj2]]
[2018-09-02T17:41:51.444+0200] [Payara 4.1] [INFO] [] [...] [tid: _ThreadID=28 _ThreadName=http-thread-pool::http-listener-1(2)] [timeMillis: 1535903502432] [levelValue: 800] [[
Persisted obj3]]
[2018-09-02T17:41:51.555+0200] [Payara 4.1] [INFO] [] [...] [tid: _ThreadID=28 _ThreadName=http-thread-pool::http-listener-1(2)] [timeMillis: 1535903502432] [levelValue: 800] [[
Method finished.]]
[2018-09-02T17:41:51.789+0200] [Payara 4.1] [INFO] [] [] [tid: _ThreadID=27 _ThreadName=http-thread-pool::http-listener-1(1)] [timeMillis: 1535902911789] [levelValue: 800] [[
Hibernate: insert into ... // obj1
[2018-09-02T17:41:51.929+0200] [Payara 4.1] [INFO] [] [] [tid: _ThreadID=27 _ThreadName=http-thread-pool::http-listener-1(1)] [timeMillis: 1535902911929] [levelValue: 800] [[
Hibernate: insert into ... // obj2
[2018-09-02T17:41:51.931+0200] [Payara 4.1] [INFO] [] [] [tid: _ThreadID=27 _ThreadName=http-thread-pool::http-listener-1(1)] [timeMillis: 1535902911931] [levelValue: 800] [[
Hibernate: insert into ... // obj3
[2018-09-02T17:41:51.939+0200] [Payara 4.1] [WARN] [] [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] [tid: _ThreadID=27 _ThreadName=http-thread-pool::http-listener-1(1)] [timeMillis: 1535902911939] [levelValue: 900] [[
SQL Error: 12899, SQLState: 72000]]
[2018-09-02T17:41:51.939+0200] [Payara 4.1] [ERROR] [] [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] [tid: _ThreadID=27 _ThreadName=http-thread-pool::http-listener-1(1)] [timeMillis: 1535902911939] [levelValue: 1000] [[
ORA-12899: Wert zu groß für Spalte "FIELD2" (aktuell: 7, maximal: 1)
]]
[2018-09-02T17:41:51.941+0200] [Payara 4.1] [INFO] [] [org.hibernate.engine.jdbc.batch.internal.AbstractBatchImpl] [tid: _ThreadID=27 _ThreadName=http-thread-pool::http-listener-1(1)] [timeMillis: 1535902911941] [levelValue: 800] [[
HHH000010: On release of batch it still contained JDBC statements]]
[2018-09-02T17:41:51.946+0200] [Payara 4.1] [ERROR] [] [org.hibernate.internal.ExceptionMapperStandardImpl] [tid: _ThreadID=27 _ThreadName=http-thread-pool::http-listener-1(1)] [timeMillis: 1535902911946] [levelValue: 1000] [[
HHH000346: Error during managed flush [org.hibernate.exception.GenericJDBCException: could not execute statement]]]
[2018-09-02T17:41:51.946+0200] [Payara 4.1] [WARNING] [] [javax.enterprise.resource.jta.com.sun.enterprise.transaction] [tid: _ThreadID=27 _ThreadName=http-thread-pool::http-listener-1(1)] [timeMillis: 1535902911946] [levelValue: 900] [[
DTX5014: Caught exception in beforeCompletion() callback:
javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: could not execute statement
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:147)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:155)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:162)
at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1434)
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:484)
at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:3190)
at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2404)
at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:467)
at org.hibernate.resource.transaction.backend.jta.internal.JtaTransactionCoordinatorImpl.beforeCompletion(JtaTransactionCoordinatorImpl.java:320)
at org.hibernate.resource.transaction.backend.jta.internal.synchronization.SynchronizationCallbackCoordinatorNonTrackingImpl.beforeCompletion(SynchronizationCallbackCoordinatorNonTrackingImpl.java:47)
at org.hibernate.resource.transaction.backend.jta.internal.synchronization.RegisteredSynchronization.beforeCompletion(RegisteredSynchronization.java:37)
at com.sun.enterprise.transaction.JavaEETransactionImpl.commit(JavaEETransactionImpl.java:452)
at com.sun.enterprise.transaction.JavaEETransactionManagerSimplified.commit(JavaEETransactionManagerSimplified.java:879)
at com.sun.ejb.containers.EJBContainerTransactionManager.completeNewTx(EJBContainerTransactionManager.java:721)
at com.sun.ejb.containers.EJBContainerTransactionManager.postInvokeTx(EJBContainerTransactionManager.java:505)
at com.sun.ejb.containers.BaseContainer.postInvokeTx(BaseContainer.java:4536)
at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:2023)
at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:1994)
at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:220)
at com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate.invoke(EJBLocalObjectInvocationHandlerDelegate.java:90)
at com.sun.proxy.$Proxy406.testImport(Unknown Source)
at ...
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory$1.invoke(ResourceMethodInvocationHandlerFactory.java:81)
at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher$1.run(AbstractJavaResourceMethodDispatcher.java:144)
at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke(AbstractJavaResourceMethodDispatcher.java:161)
at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$ResponseOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:160)
at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:99)
at org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:389)
at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:347)
at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:102)
at org.glassfish.jersey.server.ServerRuntime$2.run(ServerRuntime.java:326)
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271)
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267)
at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
at org.glassfish.jersey.internal.Errors.process(Errors.java:267)
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:317)
at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:305)
at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1154)
at org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:473)
at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:427)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:388)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:341)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:228)
at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1606)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:258)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:160)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:654)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:593)
at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:155)
at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:371)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:238)
at com.sun.enterprise.v3.services.impl.ContainerMapper$HttpHandlerCallable.call(ContainerMapper.java:480)
at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:180)
at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:206)
at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:180)
at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:235)
at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:284)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:201)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:133)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:112)
at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:539)
at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:112)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:117)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:56)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:137)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:593)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:573)
at java.lang.Thread.run(Thread.java:748)
Caused by: org.hibernate.exception.GenericJDBCException: could not execute statement
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:47)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:111)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:97)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:207)
at org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:45)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3001)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3501)
at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:89)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:586)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:460)
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:337)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39)
at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1428)
... 72 more
Caused by: java.sql.SQLException: ORA-12899: Wert zu groß für Spalte "FIELD2" (aktuell: 7, maximal: 1)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:450)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:399)
at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:1059)
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:522)
at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:257)
at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:587)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:225)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:53)
at oracle.jdbc.driver.T4CPreparedStatement.executeForRows(T4CPreparedStatement.java:943)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1150)
at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:4798)
at oracle.jdbc.driver.OraclePreparedStatement.executeUpdate(OraclePreparedStatement.java:4875)
at oracle.jdbc.driver.OraclePreparedStatementWrapper.executeUpdate(OraclePreparedStatementWrapper.java:1361)
at com.sun.gjc.spi.base.PreparedStatementWrapper.executeUpdate(PreparedStatementWrapper.java:125)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:204)
... 81 more
]]
有人能解释一下为什么有效的插入语句被执行而不是回滚吗?我能做些什么来实现完全回滚?我想要的行为是在我的事务中将所有条目插入数据库,或者根本没有条目(以防任何错误)。
最后我解决了我的问题。问题是在我使用的Payara服务器配置中没有注册jdbc-资源。将其添加到domain.xml
中的服务器配置后,一切都按预期工作。
<resources>
<jdbc-resource pool-name="pool-name" jndi-name="jdbc/name"></jdbc-resource>
<jdbc-connection-pool ...> </jdbc-connection-pool>
</resources>
...
<servers>
<server config-ref="server-config" name="server">
...
<resource-ref ref="jdbc/name"></resource-ref>
</server>
</servers>
Spring 4.1.4 Hibernate 4.2.0 JDK 1.8 我的上下文:我有一个控制器调用-->Service-->调用Dao业务功能是删除(在1到许多DB关系中)一些子级,但不是所有子级。然后,在删除了一些子项之后,我尝试删除父项,然后我得到了java.sql.SqlIntegrityConstraintViolationException
情景故事时间: 我“继承”了一个程序,一个用于访问数据库的相当简单的webservice。该程序在某个地方有一个缺陷:它试图更新一个没有更新授权的表。该程序只具有更新数据库队列的权限(Oracle),以保存谁访问了什么信息。这是不受欢迎的行为,现在我纠正了它。注意:这与这个问题本身无关,它只是导致我提出这个问题的原因。 该程序使用Spring+Hibernate来管理和访问数据和事务。 因为程序的
我试图编写一个spring-cloud-stream函数(spring-starter-parent 2.5.3,java 11,spring-cloud-version 2020.0.3),该函数同时具有Kafka和Postgres事务。每当使用的消息以字符串“fail”开始时,该函数将引发一个模拟错误,我希望这将导致数据库事务回滚,然后导致kafka事务回滚。(我知道Kafka交易不是XA,这
public void A()抛出ApplicationException{ } 这是方法B(): } 显然,如果删除方法B()中的catch块,就不会出现这种行为。现在,我想知道是否有一种方法可以回滚我的事务,即使我捕捉到方法B()中的异常。谢谢!!!!
问题内容: 我正在尝试更改持久对象的ID。我在Hibernate和MySQL中使用JPA。我执行代码时遇到的错误是:org.hibernate.HibernateException:com.tutorial.jpa.certification.listing5_18.AA实例的标识符从2更改为99 我找不到此问题的答案,因此在此感谢您的帮助。代码为: 问题答案: 您永远不要修改实体的主键 -这定义
我正在与用propagation.requires_new注释的方法的奇怪行为作斗争。 以下是TransactionManager的日志: