Spring JDBC与事务管理8:Spring声明式事务三:【注解形式】配置声明式事务;

本文介绍了如何在Spring框架中使用注解方式配置声明式事务,包括配置步骤、关键类的设置、EmployeeDao和Service类的注解应用,以及事务传播策略的实践。通过pom.xml引入依赖,详细展示了如何在applicationContext.xml中启用注解事务管理和具体类方法的事务声明。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

说明:

(1)同理,Spring这个机构,也提供了【使用注解方式,配置声明式事务】的策略;

(2)本篇博客的IoC容器也采用了注解方式;

(3)本篇博客的代码的业务逻辑和【Spring JDBC与事务管理7:Spring声明式事务二:事务传播方式;】一样;只是本篇博客的声明式事务是采用注解形式来配置的而已;

(4)【注解形式】配置声明式事务很简单,主要包括两部分:

     ● 在applicationContext.xml中使用【<tx:annotation-driven transaction-manager="transactionManager"/>】 :启用注解形式声明事务;

     ● 然后,在需要事务控制的类、方法上使用【@Transactional注解】;

(5)在实际开发中,声明事务的常用配置和开发习惯,这个需要慢慢积累;

目录

一:【注解形式】配置声明式事务;

(1)pom.xml:引入所需依赖;

(2)applicationContext.xml:配置公用类对象;启用注解形式声明事务;

(3)EmployeeDao类:一个简单的Dao类;

(4)EmployeeService:一个简单的Service类;使用注解配置了声明式事务;

(5)BatchService:一个简单的Service类;使用注解配置了声明式事务;

(6)测试;


 

一:【注解形式】配置声明式事务;

 

(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日志组件,Spring框架默认集成-->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.3</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.5</version>
        </dependency>
    </dependencies>

</project>

说明:

(1)没什么好说的,目前在pom.xml中,引入了【Spring Context模块】,【Spring JDBC模块】,【MySQL JDBC驱动】,【junit测试依赖】,【Spring Test模块】,【logback日志依赖】,【Spring AOP底层依赖的aspectjweaver】这几个;

(2)applicationContext.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:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"
       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
        http://www.springframework.org/schema/tx
        https://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/aop/spring-aop.xsd">
    <context:component-scan base-package="com.imooc"/>
    <!--数据源-->
    <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&amp;useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=Asia/Shanghai&amp;allowPublicKeyRetrieval=true"/>
        <property name="username" value="root"/>
        <property name="password" value="12345"/>
    </bean>
    <!--JdbcTemplate-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <!--事务管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <!-- 启用注解形式声明式事务 -->
    <tx:annotation-driven transaction-manager="transactionManager"/>
</beans>

说明:

(1)【  <context:component-scan base-package="com.imooc"/>】意思是组件扫描,其作用是:确定扫描的包的范围是什么;(这个在【Spring IoC容器与Bean管理21:使用注解方式实现Spring IoC二:组件类型注解】中第一次接触过);

(2)即使我们这儿是使用注解方式配置声明式事务;但是,DriverManagerDataSource数据源类,JdbcTemplate核心类,DataSourceTransactionManager事务管理器类这三个系统底层的公用类,还是需要采用XML方式进行配置;

(3)【<tx:annotation-driven transaction-manager="transactionManager"/>】 :启用注解形式声明事务;写了这句话后,就能完成【注解形式声明式事务的底层设置】了;(为了能更好的理解这句话,可以快速参考【Spring AOP面向切面编程8:基于注解开发Spring AOP;】和【Spring JDBC与事务管理6:Spring声明式事务一:声明式事务配置;】)

(3)EmployeeDao类:一个简单的Dao类;

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 org.springframework.stereotype.Repository;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
@Repository
public class EmployeeDao {
    @Resource
    private JdbcTemplate jdbcTemplate;

    public Employee findById(Integer eno){
        String sql = "select * from employee where eno = ?";
        //查询单条数据
        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 = ?";
        //查询复合数据
        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 = ?";
        //将查询结果作为Map进行封装
        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(?,?,?,?,?)";
        //利用update方法实现数据写入操作
        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;
    }
}

说明:

(1)这儿我们也使用注解方式配置IoC容器了;PS:为了少点麻烦,要注意如下这种的名字的对应:

(2)EmployeeDao没什么好说的,就是使用注解形式配置IoC,然后使用注解完成对象的注入;

(4)EmployeeService:一个简单的Service类;使用注解配置了声明式事务;

package com.imooc.spring.jdbc.service;

import com.imooc.spring.jdbc.dao.EmployeeDao;
import com.imooc.spring.jdbc.entity.Employee;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
@Service
//声明式事务核心注解
//放在类上,将声明式事务配置应用于当前类所有方法,默认事务传播为 REQUIRED
@Transactional
public class EmployeeService {
    @Resource
    private EmployeeDao employeeDao;
    @Resource
    private BatchService batchService;

    @Transactional(propagation = Propagation.NOT_SUPPORTED , readOnly = true)
    public Employee findById(Integer eno){
        return employeeDao.findById(eno);
    }

    public void batchImport() {
        for (int i = 1; i <= 10; i++) {
            if(i==3){
                throw new RuntimeException("意料之外的异常");
            }
            Employee employee = new Employee();
            employee.setEno(8000 + i);
            employee.setEname("员工" + i);
            employee.setSalary(4000f);
            employee.setDname("市场部");
            employee.setHiredate(new Date());
            employeeDao.insert(employee);
        }
    }

    public void startImportJob(){
        batchService.importJob1();
        if(1==1){
            throw new RuntimeException("意料之外的异常");
        }
        batchService.importJob2();
        System.out.println("批量导入成功");
    }

    public EmployeeDao getEmployeeDao() {
        return employeeDao;
    }

    public void setEmployeeDao(EmployeeDao employeeDao) {
        this.employeeDao = employeeDao;
    }

    public BatchService getBatchService() {
        return batchService;
    }

    public void setBatchService(BatchService batchService) {
        this.batchService = batchService;
    }
}

说明:

(1)对于EmployeeService,我们也使用注解方式配置其IoC;

(2)在类上使用【@Transactional注解】,传播方式默认为REQURIED;那么这个在类上的配置,会应用到本类的所有方法上;

(3)在方法上使用【@Transactional注解】,则该方法优先使用在本方法上配置的事务传播方式;

(4)即【@Transactional注解】可以用在类上,也可以用在方法上;

          ● 写在类上的【@Transactional注解】,会作用在本类的所有方法上;

          ● 写在方法上的【@Transactional注解】, 只对当前方法生效;

          ● 在加载是时候,写在方法上的【@Transactional注解】比写在类上的【@Transactional注解】优先级高;

(5)BatchService:一个简单的Service类;使用注解配置了声明式事务;

package com.imooc.spring.jdbc.service;

import com.imooc.spring.jdbc.dao.EmployeeDao;
import com.imooc.spring.jdbc.entity.Employee;
import com.sun.xml.internal.ws.developer.Serialization;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
@Service
@Transactional(propagation = Propagation.NOT_SUPPORTED,readOnly = true)
public class BatchService {
    @Resource
    private EmployeeDao employeeDao;
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void importJob1(){
        for (int i = 1; i <= 10; i++) {
            Employee employee = new Employee();
            employee.setEno(8000 + i);
            employee.setEname("研发部员工" + i);
            employee.setSalary(4000f);
            employee.setDname("研发部");
            employee.setHiredate(new Date());
            employeeDao.insert(employee);
        }
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void importJob2(){
        for (int i = 1; i <= 10; i++) {
            Employee employee = new Employee();
            employee.setEno(9000 + i);
            employee.setEname("市场部员工" + i);
            employee.setSalary(4500f);
            employee.setDname("市场部");
            employee.setHiredate(new Date());
            employeeDao.insert(employee);
        }
    }

    public EmployeeDao getEmployeeDao() {
        return employeeDao;
    }

    public void setEmployeeDao(EmployeeDao employeeDao) {
        this.employeeDao = employeeDao;
    }
}

说明:

(1)对于BatchService,我们也使用注解方式配置其IoC;

(2)在类上使用【@Transactional注解】;因为按照业务需求,BatchService中的方法都需要在独立的事务中运行,所以在BatchService的类上使用如下配置:

(6)测试;

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值