Spring Transaction

The following article explains how to solve problems with the Spring JDBC example.
Modify the applicationContext.xml as shown 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="shinhanBank" />
	</bean>

	<bean id="shinhanBank" class="net.java_school.bank.ShinhanBank">
		<property name="dao" ref="shinhanBankDao" />
	</bean>

	<bean id="shinhanBankDao" class="net.java_school.bank.ShinhanBankDao">
		<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 the deposit and withdrawal methods are designed to return void, it is not known whether the deposit or withdrawal was successful.
Modify methods to return an integer value for deposits and withdrawals.

BankDao.java
public int deposit(String accountNo, long amount);

public int withdraw(String accountNo, long amount);
ShinhanBankDao.java
@Override
public int deposit(String accountNo, long 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, long 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 as follows:

ShinhanBank.java
package net.java_school.bank;

import java.util.List;

import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Transactional(propagation=Propagation.SUPPORTS)
public class ShinhanBank implements Bank {
	
	//..omit..
	
	@Override
	@Transactional(propagation=Propagation.REQUIRED)
	public void transfer(String from, String to, long amount) {
		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!");
		}
	}

	//..omit..
	
}

Modify the main method of BankUi.java as follows.

ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); //XML
//AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(BankConfig.class); //JavaConfig

Try to transfer some money from 101 accounts to 505 accounts which do not exist.
It is a success if the transfer is canceled and the balance of the 101 account is not reduced.
Remove the @Transactional(propagation = Propagation.REQUIRED) above the transfer() method in the ShinhanBank.java and try transfer again to see the difference.

JavaConfig configuration

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 shinhanBankDao() {
        ShinhanBankDao bankDao = new ShinhanBankDao();
        bankDao.setDataSource(dataSource());
        return bankDao;
    }

	@Bean
	public Bank shinhanBank() {
		Bank bank = new ShinhanBank();
		bank.setDao(shinhanBankDao());
		return bank;
	}

	@Bean
	public BankUi bankUi() {
		BankUi ui = new BankUi();
		ui.setBank(shinhanBank());
		ui.setStream(System.out);
		return ui;
	}
	
}

First of all, comment out all settings in applicationContext.xml.
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