I also suggest you read chapter 6 of the reference guide which explains how AOP with spring works.
Did a new run through 6,9 and 11 .. and I stil learn new stuff.
Also I really believe it belongs in the service layer
Yes yes - i made the service class. I just hate creating a new class that are just calling 2 methods. Bloat.
But I did, cause after reading(and your comment) I was suspecting that spring maybe wasn't able to create the proxy on the action class, since Its not created by spring.
My Dao, and Service classes implements their own interfaces and are injected(ioc) with spring here and there.
So I created this new service class, and injects it, and hoped spring would find things easier.
Code:
// config
<bean id="myService" class="com.service.impl.MyServiceImpl">
<property name="myRepository" ref="myRepository"/>
</bean>
//code
public class MyServiceImpl implements MyService
{
private MyRepository myRepository;
@Transactional
public void update( List<Person> list )
{
myRepository.update( list ); //my other sql
myRepository.updateProcedure( list );
}
public void setMyRepository( MyRepository myRepository )
{
this.myRepository = myRepository;
}
}
result:
update are updating and commited.
updateProcedure gets an exception, and are not run.
Thats not supposed to happen...
I can't se in doc that JdbcTemplate().batchUpdate() explisitly commits, which I for a moment suspected it to do.
Then I turned logging on(somehow not managed that before, so I have always coded in blind).
What I do see in the log is that the proxy is added with JdkDynamicAopProxy, I see the TransactionInterceptor, and in the log I do see that rollback is done. But I don't find anything that should tell me that the first sql is commited. On normal sql the autocommit is on, so I don't see any explisit commit done there either.
Code:
org.springframework.jdbc.datasource.DataSourceTransactionManager - Using transaction object [org.springframework.jdbc.datasource.DataSourceTransactionManager$DataSourceTransactionObject@1da0a1]
org.springframework.jdbc.datasource.DataSourceTransactionManager - Creating new transaction with name [com.service.MyService.update]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
org.springframework.jdbc.datasource.DataSourceTransactionManager - Acquired Connection [jdbc:oracle:thin:@*******, UserName=****, Oracle JDBC driver] for JDBC transaction
org.springframework.jdbc.datasource.DataSourceTransactionManager - Switching JDBC Connection [jdbc:oracle:thin:@******, UserName=******, Oracle JDBC driver] to manual commit
org.springframework.transaction.support.TransactionSynchronizationManager - Bound value [org.springframework.jdbc.datasource.ConnectionHolder@125f027] for key [org.apache.tomcat.dbcp.dbcp.BasicDataSource@9830bc] to thread [http-8081-Processor25]
org.springframework.transaction.support.TransactionSynchronizationManager - Initializing transaction synchronization
org.springframework.jdbc.core.JdbcTemplate - Executing SQL batch update [update sql goes here]
org.springframework.jdbc.core.JdbcTemplate - Executing prepared SQL statement [update sql goes here]
org.springframework.transaction.support.TransactionSynchronizationManager - Retrieved value [org.springframework.jdbc.datasource.ConnectionHolder@125f027] for key [org.apache.tomcat.dbcp.dbcp.BasicDataSource@9830bc] bound to thread [http-8081-Processor25]
org.springframework.transaction.support.TransactionSynchronizationManager - Retrieved value [org.springframework.jdbc.datasource.ConnectionHolder@125f027] for key [org.apache.tomcat.dbcp.dbcp.BasicDataSource@9830bc] bound to thread [http-8081-Processor25]
org.springframework.jdbc.support.JdbcUtils - JDBC driver supports batch updates
org.springframework.transaction.support.TransactionSynchronizationManager - Retrieved value [org.springframework.jdbc.datasource.ConnectionHolder@125f027] for key [org.apache.tomcat.dbcp.dbcp.BasicDataSource@9830bc] bound to thread [http-8081-Processor25]
org.springframework.jdbc.core.JdbcTemplate - Executing SQL batch update [{call myschema.myProc( ?, ? null, ? )}]
org.springframework.jdbc.core.JdbcTemplate - Executing prepared SQL statement [{call myschema.myProc( ?, ? null, ? )}]
org.springframework.transaction.support.TransactionSynchronizationManager - Retrieved value [org.springframework.jdbc.datasource.ConnectionHolder@125f027] for key [org.apache.tomcat.dbcp.dbcp.BasicDataSource@9830bc] bound to thread [http-8081-Processor25]
org.springframework.transaction.support.TransactionSynchronizationManager - Retrieved value [org.springframework.jdbc.datasource.ConnectionHolder@125f027] for key [org.apache.tomcat.dbcp.dbcp.BasicDataSource@9830bc] bound to thread [http-8081-Processor25]
org.springframework.jdbc.support.JdbcUtils - JDBC driver supports batch updates
org.springframework.transaction.support.TransactionSynchronizationManager - Retrieved value [org.springframework.jdbc.datasource.ConnectionHolder@125f027] for key [org.apache.tomcat.dbcp.dbcp.BasicDataSource@9830bc] bound to thread [http-8081-Processor25]
org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator - Using nested SQLException from the BatchUpdateException
org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator - Unable to translate SQLException with Error code '1476', will now try the fallback translator
org.springframework.jdbc.datasource.DataSourceTransactionManager - Triggering beforeCompletion synchronization
org.springframework.jdbc.datasource.DataSourceTransactionManager - Initiating transaction rollback
org.springframework.jdbc.datasource.DataSourceTransactionManager - Rolling back JDBC transaction on Connection [jdbc:oracle:thin:@*****, UserName=***, Oracle JDBC driver]
org.springframework.jdbc.datasource.DataSourceTransactionManager - Triggering afterCompletion synchronization
org.springframework.transaction.support.TransactionSynchronizationManager - Clearing transaction synchronization
org.springframework.transaction.support.TransactionSynchronizationManager - Removed value [org.springframework.jdbc.datasource.ConnectionHolder@125f027] for key [org.apache.tomcat.dbcp.dbcp.BasicDataSource@9830bc] from thread [http-8081-Processor25]
org.springframework.jdbc.datasource.DataSourceTransactionManager - Releasing JDBC Connection [jdbc:oracle:thin:@******, UserName=******, Oracle JDBC driver] after transaction
org.springframework.jdbc.datasource.DataSourceUtils - Returning JDBC Connection to DataSource
org.springframework.dao.DataIntegrityViolationException: PreparedStatementCallback; SQL [{call myschema.myProc( ?, ? null, ? )}]; ORA-01476: divisor is equal to zero
ORA-06512: at "*********", line 263
ORA-06512: at line 1
; nested exception is java.sql.SQLException: ORA-01476: divisor is equal to zero
ORA-06512: at "***********", line 263
ORA-06512: at line 1
at org.springframework.jdbc.support.SQLStateSQLExceptionTranslator.translate(SQLStateSQLExceptionTranslator.java:111)
at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.translate(SQLErrorCodeSQLExceptionTranslator.java:322)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:582)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:594)
at org.springframework.jdbc.core.JdbcTemplate.batchUpdate(JdbcTemplate.java:841)
at com.dao.impl.MyDao.updateProcedure(MyDao.java:294)
at com.service.impl.MyServiceImpl.update(MyServiceImpl.java:20)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:301)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
at $Proxy24.update(Unknown Source)
at com.actions.MyAction.save(MyAction.java:111)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
It turns of autocommit, does it stuffs, on failure it rollback(I belive), and the exception is an runtime exception which should trigger rollback if I got that correct
If the error is removed from the SP, and it runs nice, then I see the commit beeing done in the log.
What am I missing...