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&characterEncoding=UTF-8&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&characterEncoding=UTF-8&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
- Write transfer cases (both business and persistent)
- 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&characterEncoding=UTF-8&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&characterEncoding=UTF-8&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.
-
Atomicity
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):
- Read uncommitted: At the lowest level, nothing can be guaranteed.
- Read committed: Avoid dirty reading
- Repeatable read: Avoid dirty, non-repeatable reading
- 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)
- XML based on AspectJ (focus)
- 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: