Spring JDBC Implementation for Spring Applications

Keywords: Java Spring JDBC MySQL

Getting started with the jdbcTemplate class

Mode 1

POM.XML

<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>spring-aop</groupId>
    <artifactId>spring-aop</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <dependencies>
        <!-- spring ioc Dependent packages required by components -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>5.2.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>5.2.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-expression</artifactId>
            <version>5.2.1.RELEASE</version>
        </dependency>
        <!-- Be based on AspectJ Of aop Dependent Packages -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>5.2.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>aopalliance</groupId>
            <artifactId>aopalliance</artifactId>
            <version>1.0</version>
        </dependency>
        <!-- spring Transaction Management and JDBC Dependent Packages -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>5.2.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.2.1.RELEASE</version>
        </dependency>
        <!-- spring Unit Test Component Package -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.2.1.RELEASE</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <!-- MySql Database Driven Package -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.18</version>
        </dependency>
    </dependencies>
</project>

Modify jdk version

    <build>
        <plugins>
            <!-- To configure Maven Of JDK Compile Level -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.2</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
        </plugins>
    </build>

Test Unit

package com.cyb.spring.test;

import org.junit.Test;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;

public class TestJdbcTemplate {
    @Test
    public void test() {
        try {
            //Create connection pool, use first spring Frame built-in connection pool
            DriverManagerDataSource dataSource =new DriverManagerDataSource();
            //Database Driver
            //dataSource.setDriverClassName("com.mysql.jdbc.Driver");  //Old Driver
            dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver"); //New Driver
            //Database Connection String
            dataSource.setUrl("jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai");
            //Account number
            dataSource.setUsername("root");
            //Password
            dataSource.setPassword("root");
            //Create Template Class
            JdbcTemplate jdbcTemplate=new JdbcTemplate(dataSource);
            //Complete adding data
            int res = jdbcTemplate.update("insert into s_user values (null,?,?)",22,"Tester");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Mode 2

spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">
    <!-- Administration DataSource -->
    <bean id="dataSource"
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <!-- set Method injection properties, independent of member properties in the class, and set The method name is related, for example, to an attribute called username,however set Method: setName -->
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://localhost:3306/demo?useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=Asia/Shanghai"></property>
        <property name="username" value="root"></property>
        <property name="password" value="root"></property>
    </bean>
    <!-- Administration jdbcTemplate -->
    <bean id="template"
        class="org.springframework.jdbc.core.JdbcTemplate">
        <constructor-arg name="dataSource" ref="dataSource"></constructor-arg>
    </bean>
</beans>

unit testing

package com.cyb.spring.test;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:spring.xml")
public class TestJdbcTemplate {
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Test
    public void test() {
        try {
            int res = jdbcTemplate.update("insert into s_user values (null,?,?)",22,"Tester");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
}

Spring Manages Third Party DataSource s

Common Data Source Connection Pool

  • dbcp
  • c3p0
  • Druid (Ali made)

Manage DBCP connection pools

maven Project Join Dependency

pom.xml

<dependency>
    <groupId>commons-dbcp</groupId>
    <artifactId>commons-dbcp</artifactId>
    <version>1.4</version>
</dependency>

spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">
    <!-- Manage third parties DataSource -->
    <bean id="dataSource"
        class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <!-- set Method injection properties, independent of member properties in the class, and set The method name is related, for example, to an attribute called username,however set Method: setName -->
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://localhost:3306/demo?useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=Asia/Shanghai"></property>
        <property name="username" value="root"></property>
        <property name="password" value="root"></property>
    </bean>
    <!-- Administration jdbcTemplate -->
    <bean id="template"
        class="org.springframework.jdbc.core.JdbcTemplate">
        <constructor-arg name="dataSource" ref="dataSource"></constructor-arg>
    </bean>
</beans>

unit testing

package com.cyb.spring.test;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:spring.xml")
public class TestJdbcTemplate {
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Test
    public void test() {
        try {
            int res = jdbcTemplate.update("insert into s_user values (null,?,?)",22,"Tester 22");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    @Test
    public void test2() {
        try {
            //Create connection pool, use first spring Frame built-in connection pool
            DriverManagerDataSource dataSource =new DriverManagerDataSource();
            //Database Driver
            //dataSource.setDriverClassName("com.mysql.jdbc.Driver");  //Old Driver
            dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver"); //New Driver
            //Database Connection String
            dataSource.setUrl("jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai");
            //Account number
            dataSource.setUsername("root");
            //Password
            dataSource.setPassword("root");
            //Create Template Class
            JdbcTemplate jdbcTemplate=new JdbcTemplate(dataSource);
            //Complete adding data
            int res = jdbcTemplate.update("insert into s_user values (null,?,?)",22,"Tester");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Use JdbcTemplate to complete add-delete check

 s_user.java

package com.cyb.spring.test;

public class s_user {
    private int id;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "s_user [id=" + id + ", name=" + name + ", age=" + age + "]";
    }
    private String name;
    private int age;
}

TestjdbcTemplate.java

query

package com.cyb.spring.test;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:spring.xml")
public class TestJdbcTemplate {
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Test
    public void test() {
        //First parameter: executed sql Sentence
        //Second parameter: Result Mapping Processor(RowMapper)
        //Third parameter: sql Input into statement
        List<s_user> queryList = jdbcTemplate.query("select * from s_user",new MyBeanMapper(),null);
        System.out.println(queryList);
    }
}
class MyBeanMapper implements RowMapper
{

    public s_user mapRow(ResultSet rs, int rowNum) throws SQLException {
        s_user user=new s_user();
        user.setId(rs.getInt("id"));
        user.setName(rs.getString("name"));
        user.setAge(rs.getInt("age"));
        return user;
    }
}

insert

package com.cyb.spring.test;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:spring.xml")
public class TestJdbcTemplate {
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Test
    public void test() {
        try {
            int res = jdbcTemplate.update("insert into s_user values (null,?,?)",22,"Tester 22");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

To update

package com.cyb.spring.test;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:spring.xml")
public class TestJdbcTemplate {
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Test
    public void test() {
        try {
            int res = jdbcTemplate.update("update s_user set name=?,age=? where id=?","Tester",19,5);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

delete

package com.cyb.spring.test;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:spring.xml")
public class TestJdbcTemplate {
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Test
    public void test() {
        try {
            int res = jdbcTemplate.update("delete from s_user where id=?",5);
            
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

JdbcDaoSupport developed by Spring DAO

Case Design

  1. Write transfer cases (both business and persistent)
  2. Introducing the use of JdbcDaoSupport when writing DAO s

Realization

Project Structure Diagram

 

 

 

 

Database table fields

 

 pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>spring-aop</groupId>
    <artifactId>spring-aop</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <dependencies>
        <!-- spring ioc Dependent packages required by components -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>5.2.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>5.2.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-expression</artifactId>
            <version>5.2.1.RELEASE</version>
        </dependency>
        <!-- Be based on AspectJ Of aop Dependent Packages -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>5.2.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>aopalliance</groupId>
            <artifactId>aopalliance</artifactId>
            <version>1.0</version>
        </dependency>
        <!-- spring Transaction Management and JDBC Dependent Packages -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>5.2.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.2.1.RELEASE</version>
        </dependency>
        <!-- spring Unit Test Component Package -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.2.1.RELEASE</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <!-- MySql Database Driven Package -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.18</version>
        </dependency>
        <!-- dbcp Connection pool dependent packages -->
        <dependency>
            <groupId>commons-dbcp</groupId>
            <artifactId>commons-dbcp</artifactId>
            <version>1.4</version>
        </dependency>
        <dependency>
            <groupId>javax.annotation</groupId>
            <artifactId>javax.annotation-api</artifactId>
            <version>1.3.1</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <!-- To configure Maven Of JDK Compile Level -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.2</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

AccountDao.java

package com.cyb.spring.dao;

public interface AccountDao {
    void update(String name, int money);
    int queryMoney(String name);
}

AccountDaoImpl.java

Mode 1

package com.cyb.spring.dao;

import java.sql.ResultSet;
import java.sql.SQLException;

import javax.annotation.Resource;

import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
@Repository
public class AccountDaoImpl implements AccountDao {

    @Resource
    private JdbcTemplate jdbcTemplate;

    public void update(String name, int money) {
        // jdbc operation
        // MyBatis operation
        // JdbcTemplate operation
        jdbcTemplate.update("UPDATE s_account set money=" + money + " where name='" + name + "'");
    }

    public int queryMoney(String name) {
        int money = jdbcTemplate.queryForObject("select money from s_account where name=?", new IntMapper(),
                name);
        return money;
    }
}

class IntMapper implements RowMapper<Integer> {

    public Integer mapRow(ResultSet rs, int rowNum) throws SQLException {
        return rs.getInt("money");
    }
}

Mode 2

package com.cyb.spring.dao;

import java.sql.ResultSet;
import java.sql.SQLException;

import javax.annotation.Resource;

import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import org.springframework.stereotype.Repository;
@Repository
public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao {
    public void update(String name, int money) {
        this.getJdbcTemplate().update("UPDATE s_account set money=" + money + " where name='" + name + "'");
    }

    public int queryMoney(String name) {
        int money=this.getJdbcTemplate().queryForObject("select money from s_account where name=?", new IntMapper(),
                name);
        return money;
    }
}

class IntMapper implements RowMapper<Integer> {

    public Integer mapRow(ResultSet rs, int rowNum) throws SQLException {
        return rs.getInt("money");
    }
}

AccountService.java

package com.cyb.spring.service;

public interface AccountService {
    void transfer(String from, String to, int money);
}

AccountServiceImpl.java

Mode 1

package com.cyb.spring.service;

import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import com.cyb.spring.dao.AccountDao;
@Service
public class AccountServiceImpl implements AccountService {
    @Resource
    private AccountDao dao;
    public void transfer(String from, String to, int money) {
        //Query first from Money for the account
        int fromMoney=dao.queryMoney(from);
        // Yes from Account deducts money
        dao.update(from, fromMoney-money);
        // Yes to Account Plus Action
        int toMoney=dao.queryMoney(to);
        dao.update(to, toMoney+money);
    }
}

Mode 2

package com.cyb.spring.service;

import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import com.cyb.spring.dao.AccountDao;
@Service
public class AccountServiceImpl implements AccountService {
    private AccountDao accountDao;
    public AccountDao getAccountDao() {
        return accountDao;
    }
    public void setAccountDao(AccountDao accountDao) {
        this.accountDao = accountDao;
    }
    public void transfer(String from, String to, int money) {
        //Query first from Money for the account
        int fromMoney=accountDao.queryMoney(from);
        // Yes from Account deducts money
        accountDao.update(from, fromMoney-money);
        // Yes to Account Plus Action
        int toMoney=accountDao.queryMoney(to);
        accountDao.update(to, toMoney+money);
    }
}

spring-transfer.xml

Mode 1

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">
    <!-- From bottom to top -->
    <bean id="dataSource"
        class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <!-- set Method injection properties, independent of member properties in the class, and set The method name is related, for example, to an attribute called username,however set Method: setName -->
        <property name="driverClassName"
            value="com.mysql.cj.jdbc.Driver"></property>
        <property name="url"
            value="jdbc:mysql://localhost:3306/demo?useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=Asia/Shanghai"></property>
        <property name="username" value="root"></property>
        <property name="password" value="root"></property>
    </bean>
    <!-- Administration jdbcTemplate -->
    <bean id="template"
        class="org.springframework.jdbc.core.JdbcTemplate">
        <constructor-arg name="dataSource" ref="dataSource"></constructor-arg>
    </bean>
    <!-- AccountDao and AccountService -->
    <context:component-scan base-package="com.cyb.spring"></context:component-scan>
</beans>

Mode 2

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">
    <!-- From bottom to top -->
    <bean id="dataSource"
        class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <!-- set Method injection properties, independent of member properties in the class, and set The method name is related, for example, to an attribute called username,however set Method: setName -->
        <property name="driverClassName"
            value="com.mysql.cj.jdbc.Driver"></property>
        <property name="url"
            value="jdbc:mysql://localhost:3306/demo?useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=Asia/Shanghai"></property>
        <property name="username" value="root"></property>
        <property name="password" value="root"></property>
    </bean>
    <!-- Administration jdbcTemplate -->
    <bean id="template"
        class="org.springframework.jdbc.core.JdbcTemplate">
        <constructor-arg name="dataSource" ref="dataSource"></constructor-arg>
    </bean>
    <!-- AccountDao and AccountService -->
    <bean id="accountService"
        class="com.cyb.spring.service.AccountServiceImpl">
        <property name="accountDao" ref="accountDao"></property>
    </bean>
    <bean id="accountDao" class="com.cyb.spring.dao.AccountDaoImpl">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
</beans>

 

AccountServiceTest.java

package com.cyb.spring.service;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:spring-transfer.xml")
public class AccountServiceTest {

    @Autowired
    private AccountService Service;
    @Test
    public void testTransfer() {
        Service.transfer("Husband", "Wife", 500);
    }
}

Transactions for Spring Applications

Transaction introduction

  • Transaction: refers to a logical set of operations that make up the execution units of this transaction, either succeeding or failing together!
  • Transaction characteristics (ACID)
    • Atomicity
      • Atomicity means that all operations involved in a transaction either succeed or fail to roll back.
    • Consistency
      • Consistency means that a transaction must transform a database from one consistent state to another, that is, a transaction must be in a consistent state before and after execution.
      • In the case of transfers, assuming that the sum of money for both users A and B is 5,000, no matter how A and B transfer and earn multiple accounts, the sum of money for the two users after the transaction ends should still be 5,000, which is transaction consistency.
    • Isolation
      • Isolation is when multiple users access a database concurrently, such as when operating on the same table, the transactions opened by the database for each user cannot be interfered with by the operations of other transactions, and multiple concurrent transactions need to be isolated from each other.
    • Durability
      • Persistence refers to the fact that once a transaction is committed, changes to the data in the database type are permanent and the commit transaction will not be lost even if the database system fails.

Transaction concurrency issues (isolation causes)

Some problems may occur during concurrent operations of transactions

  • Dirty Read: One transaction reads uncommitted data from another transaction
  • Non-repeatable read: A transaction has committed data because it has read from another transaction.Causes inconsistencies in results that are read more than twice on the same record.update operation
  • Magic Read: A transaction that has read data submitted by another transaction.Causes inconsistencies in results from more than two reads of the same table.insert, delete operation

Transaction isolation level

To avoid the above scenarios, four transaction isolation levels are defined in the standard SQL specification, and different isolation levels handle transactions differently.

Four isolation levels (from low to high):

  1. Read uncommitted: At the lowest level, nothing can be guaranteed.
  2. Read committed: Avoid dirty reading
  3. Repeatable read: Avoid dirty, non-repeatable reading
  4. Serializable: Avoid dirty, non-repeatable, hallucinatory reads

Default isolation level

The default isolation level for most databases is Read committed, such as Oracle, DB2, and so on.

The default isolation level for MySQL databases is Repeatable read.

Matters needing attention

The higher the level, the more complete and consistent the data will be, but the greater the impact on concurrency performance.

For most applications, setting the isolation level of the database system to Read Committed is a priority.It avoids dirty reading and has good concurrency performance.Although it can cause concurrent problems such as unreadable and magic reads, applications can use pessimistic or optimistic locks to control these problems in individual situations where they may occur.

Transaction Management Related Classes and API s for the Spring Framework

Spring does not directly manage transactions, but rather provides a variety of transaction managers that delegate their transaction management responsibilities to transactions within the relevant platform framework provided by persistence mechanisms such as Hibernate or JTA.The interface of the Spring Transaction Manager is PlatformTransaction Manager, through which Spring provides transaction managers for platforms such as JDBC, Hibernate, etc., but the specific implementation is the work of each platform itself.

 

 

 

 

1. PlatformTransactionManager Interface -- Platform Transaction Manager. (A class that actually manages transactions).The interface has specific implementation classes, depending on the persistence layer framework, different implementation classes need to be selected!(

2. TransactionDefinition Interface -- Transaction Definition Information. (Transaction isolation level, propagation behavior, timeout, read-only)

3. TransactionStatus Interface -- Status of the transaction (whether new, committed, saved, rolled back)

 

4. Summary: Relationship between the above objects: Platform Transaction Manager truly manages transaction objects. TransactionDefinition manages transactions based on the information defined by the transaction, resulting in some states in the management transaction. Record the states in TransactionStatus es

 

5. Implementation classes and common methods in the PlatformTransactionManager interface

1. Implementation classes of interfaces

* If you use Spring's JDBC template or MyBatis (IBatis) framework, you need to select the DataSourceTransactionManager implementation class

* If you are using Hibernate's framework, you need to select the HibernateTransactionManager implementation class

 

2. Common methods of this interface

        * void commit(TransactionStatus status)

        * TransactionStatus getTransaction(TransactionDefinition definition)

        * void rollback(TransactionStatus status)

 

6. TransactionDefinition

1. Constant transaction isolation level

* static int ISOLATION_DEFAULT) -- Use the default isolation level of the database

        * static int ISOLATION_READ_UNCOMMITTED

        * static int ISOLATION_READ_COMMITTED

        * static int ISOLATION_REPEATABLE_READ

        * static int ISOLATION_SERIALIZABLE

 

2. Transaction propagation behavior constants (default values are used instead of settings)

* Explain what the propagation behavior of transactions is first: Solve method calls between business tiers!!

 

* PROPAGATION_REQUIRED (default) -- There are transactions in A, using transactions in A. If not, B will start a new transaction and include A. (Ensure A,B is in the same transaction), default!!

* PROPAGATION_SUPPORTS) -- A has transactions, using transactions in A. If there are no transactions in A, then B does not use transactions.

* PROPAGATION_MANDATORY * There are transactions in A, using transactions in A. If A has no transactions, throw an exception.

 

* PROPAGATION_REQUIRES_NEW --- A has transactions, suspend transactions in A. B creates a new transaction. (Guarantees that A,B is not in a transaction)

* PROPAGATION_NOT_SUPPORTED --- A has transactions, suspend transactions in A.

* PROPAGATION_NEVER * There was a transaction in A and an exception was thrown.

 

* PROPAGATION_NESTED * Nested transaction. When A executes, a savepoint is set at this location. If B is OK. Execution passes. If B is abnormal, run the customer rollback on demand (choose rollback to savepoint or initial state)

Classification of Transaction Management for the Spring Framework

1. Spring's programmatic transaction management (not recommended)

* Manage transactions by writing code manually (not recommended)

 

2. Spring's declarative transaction management (underlying AOP technology)

* Manage transactions through a configuration

Programmatic Transaction Management (Understanding)

1. Note: Spring provides the template class TransactionTemplate to simplify transaction management, so you can manage transactions manually by using this template class!!

 

2. Specific steps for manual programming are as follows:

Step 1: Configure a transaction manager and Spring uses the PlatformTransactionManager interface to manage transactions, so we need to use its implementation class!!

<!--Configure Transaction Manager-->

        <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

            <property name="dataSource" ref="dataSource"/>

        </bean>

 

Step 2: Configure the template for transaction management

<!--Configure the template for transaction management-->

        <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">

            <property name="transactionManager" ref="transactionManager"/>

        </bean>

 

Step 3: Inject a transaction management template into the class that requires transaction management

        <bean id="accountService" class="com.itheima.demo1.AccountServiceImpl">

            <property name="accountDao" ref="accountDao"/>

            <property name="transactionTemplate" ref="transactionTemplate"/>

        </bean>

 

Step 4: Manage transactions using templates at the business level:

//Inject Transaction Template Objects

        private TransactionTemplate transactionTemplate;

        public void setTransactionTemplate(TransactionTemplate transactionTemplate) {

            this.transactionTemplate = transactionTemplate;

        }

 

        public void pay(final String out, final String in, final double money) {

            transactionTemplate.execute(new TransactionCallbackWithoutResult() {

 

                protected void doInTransactionWithoutResult(TransactionStatus status) {

* Deduct money //

                    accountDao.outMoney(out, money);

                    int a = 10/0;

* Add money //

                    accountDao.inMoney(in, money);

                }

            });

Declarative Transaction Management (Focus)

  1. XML based on AspectJ (focus)
  2. Annotation method based on AspectJ (focus)

Realization

Prepare transfer environment:

***Business layer:

***AccountService

***AccountServiceImpl

 

 

 

***Persistence Layer:

***AccountDao

***AccountDaoImpl

***spring configuration:

***Unit test code:

 

 

 

***Configure transaction management AOP

***Platform Transaction Manager: DataSourceTransactionManager

***Transaction notification: <tx:advice id=""transaction-manager="/>

***AOP Configuration:

<aop:config>

  <aop:advisor advice-ref="" pointcut=""/>

</aop:config>

 

 

Source Code Analysis tx:advisor

Source Entry

Here you need to understand the inheritance system of TxAdviceBeanDefinitionParser, TxAdviceBeanDefinitionParser a AbstractSingleBeanDefinitionParser a AbstractBeanDefinitionParser a AbstractBeanDefinitionBeanDefinitionParser, because based on the source analysis of the loadBeanDefinitions process above, we know that the resolution of custom elements starts with the namespaceHandler.parser method, which starts with the AbstractBeanDefinitionP methodIn arser class

We focus on how to get the BeanDefinition object, so next we go to the parseInternal method, which is in AbstractSingleBeanDefinition Parser (refer to the inheritance system above)

Next, we come to the TxAdviceBeanDefinitionParser class, where both getBeanClass and doParser methods are located

Now let's focus on the TransactionInterceptor class, which is the ultimate goal of our analysis

The invokeWithInTransaction method is in the TransactionAspectSupport, the parent of the TransactionInterceptor class:

For Transaction Source, it's basically OK to see here. If you want to know how transactions are opened and committed again, go on and let's go into the createTransactionIfNecessary method to see how transactions are opened

We enter the getTransaction method in AbstractPlatformTransaction Manager to continue to understand how transactions are opened:

Next, it's time to go into the doBegin method, but it's in the specific platform transaction manager subclass, where we use the DataSourceTransactionManager subclass for source tracking:

Transaction management for DataSourceTransactionManager is achieved through the underlying JDBC code, but the underlying transaction processing is different for different platform transaction managers.

Transaction management based on AspectJ annotation (focus)

***Comment on service class or method:

*** Class with @Transactional: means that all methods in this class are transactionally managed

*** Method with @Transactional: Indicates that only this method is transacted

***Open Transaction Comment:

Posted by mrman23 on Sun, 17 Nov 2019 09:02:45 -0800