Reputation: 492
I am new to spring and working on a sample program using Spring jdbc. this is to check how spring @Trsactional working and rolling back the changes to the Db if there is an exception.
But I am not able to achieve this. Through I am raising an exception in one of the DB update, still it's inserting the data to DB and not rolling back.
I know somewhere I am making mistake but not able to figure it out. Not sure if this is a correct approach.
What I am doing :-
in main methis I am calling load methos of Global class (which has jdbcTemplate as satic member as I will this jdbcTemplate to all other classes)
Global class load methos will initiate the bean using ApplicationContext.
Creating Dbclass instance in main method and sending the jdbcTemplate as parameter.
4.creating some sample data and calling executeDb method.
5.execute DB method will create the instance of other Dbclasss and setting the jdbcTemplate which earlier I initialized using bean in main method (I have separate class for each operation - like createuser, UpdataBalance etc)
EDIT - Removed all try-catch
DB opration code:-
@Transactional(rollbackFor={Exception.class})
public void executeDB(int count) throws Exception
{
CreateAccount newacc = new CreateAccount(jdbcTemplate);
CreateUser newusr = new CreateUser(jdbcTemplate);
//BalanceUpdate newbal = new BalanceUpdate(jdbcTemplate);
newacc.addList(acclist);
newusr.addToList(usrlist);
//newbal.addList(ballist);
newusr.execute(); // insert data to db
newacc.addAccount(); // insert data to db
//newbal.addBalance(); // insert data to db
newacc.getAccList().clear();
newusr.getUserList().clear();
//newbal.getBalanceList().clear();
if(count == 5000)
{
Thread.sleep(1000);
throw new Exception("Rollback");
}
count += 1000;
//throw new Exception();
}
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-xml -->
<context:component-scan base-package="com.example"></context:component-scan>
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:@localhost:1521:xe"/>
<property name="username" value="system"/>
<property name="password" value="root"/>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<bean id="startit" class="com.example.springtransaction.GlobalClass">
<property name="jdbcTemplate" ref="jdbcTemplate"></property>
</bean>
<bean id="dbupdate" class="com.example.springtransaction.DbUpdate">
<property name="jdbcTemplate" ref="jdbcTemplate"></property>
</bean>
Upvotes: 0
Views: 353
Reputation: 159
You should remove the try - catch and define that the method throws an Exception. Something like that
@Transactional(rollbackFor={Exception.class})
public void executeDB() throws Exception
{
if(usrlist.size() >= 5)
{
CreateAccount newacc = new CreateAccount(jdbcTemplate);
CreateUser newusr = new CreateUser(jdbcTemplate);
BalanceUpdate newbal = new BalanceUpdate(jdbcTemplate);
newacc.addList(acclist);
newusr.addToList(usrlist);
newbal.addList(ballist);
newusr.execute(); // insert data to db
newacc.addAccount(); // insert data to db
newbal.addBalance(); // insert data to db - raise exception here
}
}
Update
The class that contain the executeDB() method should be a @Component and inject that component in the main class. Not create a new Dbclass() instance by your own.
In high-level the reason is that the Spring creates proxy classes upon injection for classes that declare @Transactional. You could read more about Aspect-Oriented Programming here.
Upvotes: 0
Reputation: 8758
You need to throw exception from your method not silently log it in catch block.
And for checked exceptions you need to use @Transactional(rollbackFor = {Exception.class})
.
http://www.logicbig.com/tutorials/spring-framework/spring-data-access-with-jdbc/transactional-roll-back/
https://www.catalysts.cc/en/wissenswertes/spring-transactional-rollback-on-checked-exceptions/
Upvotes: 2