explain:
(1) In[ Spring JDBC and transaction management 5: Spring programmatic transaction; ]It is known that although programming transactions are easy to understand, they may forget to write transaction control code due to programmer level problems or negligence; Therefore, declarative transaction came into being;
(2) This point should be clear: declarative transaction is not a new technology, but a typical application scenario of [Spring AOP aspect oriented programming];
1: Introduction to declarative transactions
(1) Declarative transaction is not a new technology; Instead, [Spring AOP aspect oriented programming] is just a typical application scenario;
(2) Using Spring Surround notification in AOP] can easily solve this requirement. That is, the [declarative transaction] is through the [Spring] AOP encircling notification] completes program expansion and transaction control without modifying the source code;
(3) About Spring AOP [surround notification] you can refer to it quickly[ Spring AOP aspect oriented programming 7: AOP related concepts 5: AOP notification: Around Advice surround notification; ] Contents of the;
2: Declarative transaction configuration process
Because [declarative transaction] is through [Spring] [AOP surround notification]; Therefore, the whole configuration process of [declarative transaction] is completed in the applicationContext.xml configuration file without modifying the source code;
(1) The configuration needs to be written in applicationContext.xml to configure the TransactionManager object in the IoC container. As we already know, the function of the TransactionManager object is to commit or rollback transactions;
(2) In actual development, some methods (such as adding, modifying and deleting methods) need transaction control, while others (such as query methods) do not need transaction control. Different configurations are required according to different situations;
(3) The pointcut that delimits the scope for the transaction binding;
3: Initial code: create project s02;
The content of s02 is basically the same as the code of previous blogs, except that the code related to programmatic transactions is removed;
(1)pom.xml:
<?xml version="1.0" encoding="UTF-8"?> <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>com.imooc.spring</groupId> <artifactId>jdbc</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.2.6.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.2.6.RELEASE</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.16</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>5.2.6.RELEASE</version> </dependency> <!--logback Log component,Spring Framework default integration--> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.2.3</version> </dependency> </dependencies> </project>
explain:
(1) There is nothing to say. At present, Spring is introduced into pom.xml Context module, Spring JDBC module, MySQL Jdbc driver, junit test dependency, Spring Test module and logback log dependency;
(2) Employee entity class:
package com.imooc.spring.jdbc.entity; import java.util.Date; public class Employee { private Integer eno; private String ename; private Float salary; private String dname; private Date hiredate; public Integer getEno() { return eno; } public void setEno(Integer eno) { this.eno = eno; } public String getEname() { return ename; } public void setEname(String ename) { this.ename = ename; } public Float getSalary() { return salary; } public void setSalary(Float salary) { this.salary = salary; } public String getDname() { return dname; } public void setDname(String dname) { this.dname = dname; } public Date getHiredate() { return hiredate; } public void setHiredate(Date hiredate) { this.hiredate = hiredate; } @Override public String toString() { return "Employee{" + "eno=" + eno + ", ename='" + ename + '\'' + ", salary=" + salary + ", dname='" + dname + '\'' + ", hiredate=" + hiredate + '}'; } }
explain:
(0) the Employee entity class is very simple and has nothing to say; Moreover, it has been introduced in the previous blogs;
(1) Because the role of the employee entity class is to carry and store the query contents of the database employee table; Therefore, the attribute of Employee class should be written in strict accordance with the hump naming rules and the field name of employee table;
(2) Then, write the get and set methods as usual; Then, in order to observe the content of the Employee object conveniently, the toString() method is rewritten;
(3) applicationContext.xml configuration file:
<?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:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <!-- data source --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/springjdbctest?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true"/> <property name="username" value="root"/> <property name="password" value="12345"/> </bean> <!--JdbcTemplate Provide data CRUD of API--> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"/> </bean> <bean id="employeeDao" class="com.imooc.spring.jdbc.dao.EmployeeDao"> <!--by Dao injection JdbcTemplate object--> <property name="jdbcTemplate" ref="jdbcTemplate"/> </bean> <bean id="employeeService" class="com.imooc.spring.jdbc.service.EmployeeService"> <property name="employeeDao" ref="employeeDao"/> </bean> </beans>
explain:
(1) The applicationContext.xml is very simple. There is nothing to say. It is the basic [Spring] JDBC] configuration;
(4) EmployeeDao class:
package com.imooc.spring.jdbc.dao; import com.imooc.spring.jdbc.entity.Employee; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.JdbcTemplate; import java.util.List; import java.util.Map; public class EmployeeDao { private JdbcTemplate jdbcTemplate; public Employee findById(Integer eno){ String sql = "select * from employee where eno = ?"; //Query a single piece of data Employee employee = jdbcTemplate.queryForObject(sql, new Object[]{eno}, new BeanPropertyRowMapper<Employee>(Employee.class)); return employee; } public List<Employee> findByDname(String dname){ String sql = "select * from employee where dname = ?"; //Query composite data List<Employee> list = jdbcTemplate.query(sql, new Object[]{dname}, new BeanPropertyRowMapper<Employee>(Employee.class)); return list; } public List<Map<String, Object>> findMapByDname(String dname){ String sql = "select eno as empno , salary as s from employee where dname = ?"; //Encapsulate query results as maps List<Map<String, Object>> maps = jdbcTemplate.queryForList(sql, new Object[]{dname}); return maps; } public void insert(Employee employee){ String sql = "insert into employee(eno,ename,salary,dname,hiredate) values(?,?,?,?,?)"; //Using update method to realize data writing operation jdbcTemplate.update(sql,new Object[]{ employee.getEno() , employee.getEname(),employee.getSalary(),employee.getDname() , employee.getHiredate() }); } public int update(Employee employee){ String sql = "UPDATE employee SET ename = ?, salary = ?, dname = ?, hiredate = ? WHERE eno = ?"; int count = jdbcTemplate.update(sql, new Object[]{employee.getEname(), employee.getSalary(), employee.getDname(), employee.getHiredate(), employee.getEno()}); return count; } public int delete(Integer eno){ String sql = "delete from employee where eno = ?"; return jdbcTemplate.update(sql, new Object[]{eno}); } public JdbcTemplate getJdbcTemplate() { return jdbcTemplate; } public void setJdbcTemplate(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } }
explain:
(1) Because the Dao class EmployeeDao needs to directly operate the database, the JdbcTemplate attribute is added; Naturally, the JdbcTemplate object is also injected into the EmployeeDao object in applicationContext.xml;
(2) Some query, add, delete and modify methods are defined in EmployeeDao; Moreover, it has been introduced in the previous blogs;
(5) EmployeeService class:
package com.imooc.spring.jdbc.service; import com.imooc.spring.jdbc.dao.EmployeeDao; import com.imooc.spring.jdbc.entity.Employee; import java.util.Date; public class EmployeeService { private EmployeeDao employeeDao; public void batchImport() { for (int i = 1; i <= 10; i++) { Employee employee = new Employee(); employee.setEno(8000 + i); employee.setEname("staff" + i); employee.setSalary(4000f); employee.setDname("Marketing Department"); employee.setHiredate(new Date()); employeeDao.insert(employee); } } public EmployeeDao getEmployeeDao() { return employeeDao; } public void setEmployeeDao(EmployeeDao employeeDao) { this.employeeDao = employeeDao; } }
explain:
(1) Long winded: because the Service class needs to call the methods in Dao class; Therefore, the EmployeeDao attribute is added to the EmployeeService class, and object injection is completed in the IoC container;
(2) The business method batchImport() is also added to EmployeeService; Then, we did not use those transaction control codes in the programming transaction control; To control transactions];
4: Demand description
It is known that the batchImport() business method in EmployeeService is a batch update operation; In actual development, this obviously requires transaction control.
Requirement: configure [declarative transaction] for important Service classes of the system without modifying the original code; Thus, programmers do not have to consider the problem of transactions in the process of writing code( That is, when programmers write code, they don't have to consider writing transaction control code)
5: [declarative transaction]: configuration process( Core!)
(1) Introduce aspectj into pom.xml;
(2) Configure the TransactionManager transaction manager object in applicationContext.xml;
explain:
(1) The TransactionManager transaction manager object is required for both programming transaction and declarative transaction;
(2) In[ Spring JDBC and transaction management 5: Spring programmatic transaction; ]Configuring the TransactionManager transaction manager object has been described in;
(3) In applicationContext.xml: introduce [tx] namespace and constraints[ aop] namespace and constraints;
explain:
(1) The contents of these namespaces are actually very simple and do not need to be memorized; Moreover, it is also available on the Spring official website;
(4) In applicationContext.xml: transaction notification configuration: determine which methods use transactions and which methods do not use transactions( Core!)
(5) Actual test;
First, there are exceptions:
............................................................
Then, there are no exceptions: