Spring Transaction
This section describes how to troubleshoot the transfer example in the Spring JDBC section.
Modify applicationContext.xml like below.
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean> <tx:annotation-driven transaction-manager="transactionManager" /> <aop:aspectj-autoproxy /> <bean id="testLogger" class="net.java_school.commons.TestLogger" /> <bean id="bankUi" class="net.java_school.bank.BankUi"> <property name="stream" value="#{T(System).out}" /> <property name="bank" ref="bank" /> </bean> <bean id="bank" class="net.java_school.bank.MyBank"> <property name="dao" ref="bankDao" /> </bean> <bean id="bankDao" class="net.java_school.bank.MyBankDao"> <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:@127.0.0.1:1521:XE" /> <property name="username" value="scott" /> <property name="password" value="tiger" /> </bean> </beans>
Since we made deposit and withdrawal methods to return nothing, so we don't know whether the deposit or withdrawal was successful or not.
Modify deposit and withdrawal methods to return an integer value.
BankDao.java
public int deposit(String accountNo, double amount); public int withdraw(String accountNo, double amount);
MyBankDao.java
@Override public int deposit(String accountNo, double amount) { Map<String, Object> params = new HashMap<String, Object>(); params.put("amount", amount); params.put("accountNo", accountNo); return getNamedParameterJdbcTemplate().update(DEPOSIT, params); } @Override public int withdraw(String accountNo, double amount) { Map<String, Object> params = new HashMap<String, Object>(); params.put("amount", amount); params.put("accountNo", accountNo); return getNamedParameterJdbcTemplate().update(WITHDRAW, params); }
Set the transaction using annotations like below.
MyBank.java
package net.java_school.bank; import java.util.List; import org.springframework.transaction.annotation.Transactional; public class MyBank implements Bank { //..omit.. @Override @Transactional public void transfer(String from, String to, double amount) { try { int check = dao.withdraw(from, amount); if (check < 1) throw new RuntimeException("Withdrawal Failed!"); check = dao.deposit(to, amount); if (check < 1) throw new RuntimeException("Deposit Failed!"); } catch (Exception e) { throw new RuntimeException(e); } } //..omit.. }
Modify the main method of BankUi.java like below.
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); //XML //AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(BankConfig.class); //JavaConfig
Try to transfer some money from account 101 to account 505 that do not exist. You can see that the transaction manager cancels the transfer, leaving the balance in account 101 intact.
Remove the @Transactional(propagation = Propagation.REQUIRED) above the transfer() method in the MyBank.java and try transfer again to see the difference.
JavaConfig
BankConfig.java
package net.java_school.bank; import javax.sql.DataSource; import net.java_school.commons.TestLogger; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableAspectJAutoProxy; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.jdbc.datasource.DriverManagerDataSource; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.EnableTransactionManagement; @Configuration @EnableAspectJAutoProxy @EnableTransactionManagement public class BankConfig { @Bean public TestLogger testLogger() { return new TestLogger(); } @Bean public DataSource dataSource() { DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName("oracle.jdbc.driver.OracleDriver"); dataSource.setUrl("jdbc:oracle:thin:@127.0.0.1:1521:XE"); dataSource.setUsername("scott"); dataSource.setPassword("tiger"); return dataSource; } @Bean public PlatformTransactionManager transactionManager() { return new DataSourceTransactionManager(dataSource()); } @Bean public BankDao bankDao() { MyBankDao bankDao = new MyBankDao(); bankDao.setDataSource(dataSource()); return bankDao; } @Bean public Bank bank() { Bank bank = new MyBank(); bank.setDao(bankDao()); return bank; } @Bean public BankUi bankUi() { BankUi ui = new BankUi(); ui.setBank(bank()); ui.setStream(System.out); return ui; } }
First, comment out all contents of the beans element in applicationContext.xml and modify the main method of BankUi.java as shown below.
//ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); //XML AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(BankConfig.class); //JavaConfig
Final Source: https://github.com/kimjonghoon/transaction