W
e
l
c
o
m
e
: )

Spring JDBC与事务管理

Spring JDBC

  • Spring JDBC是Spring框架用于处理关系型数据库的模块
  • SPring JDBC对JDBC API进行封装,极大简化了开发过程
  • JdbcTemplate是Spring JDBC核心类,提供数据CRUD(增删改查)方法

初始化JDBC

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">
    <!-- 数据源设置 -->
    <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/hua?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="123456"/>
    </bean>
    <!-- JdbcTemplate提供数据CRUD的API -->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <bean id="employeeDao" class="com.hua.spring.jdbc.dao.EmployeeDao">
        <!-- 为Dao注入JdbcTemplate对象 -->
        <property name="jdbcTemplate" ref="jdbcTemplate"/>
    </bean>
</beans>

执行SQL

public class EmployeeDao {
    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> employeeList = jdbcTemplate.query(sql, new Object[]{dname}, new BeanPropertyRowMapper<Employee>(Employee.class));
        return employeeList;
    }

    public List<Map<String, Object>> findMapByDname(String dname) {
        String sql = "select eno as '员工编号', salary as '工资' 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) value(?,?,?,?,?)";
        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 = ?";
        int count = jdbcTemplate.update(sql, new Object[]{eno});
        return count;
    }

    public JdbcTemplate getJdbcTemplate() {
        return jdbcTemplate;
    }

    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }
}

Spring编程式事务

  • 编程式事务是指通过代码手动提交回滚事务的事务控制方法
  • SpringJDBC通过TransactionManager事务管理器实现事务控制
  • 事务管理器提供commit/rollback方法进行事务提交与回滚

引入事务管理器

<!--事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <!--绑定前边创建好的DateSource-->
    <property name="dataSource" ref="dataSource"/>
</bean>
public void bachInput() {
    // 定义了事务默认的标准配置
    TransactionDefinition definition = new DefaultTransactionDefinition();
    // 开始一个事务,返回事务状态,事务状态说明当前事务的执行阶段
    TransactionStatus status = transactionManager.getTransaction(definition);
    Employee employee = new Employee();
    try {
        for (int i = 1; i < 10; i++) {
            /*if (i == 3) {
                    throw new RuntimeException("运行时异常");
                }*/
            employee.setEno(8000 + i);
            employee.setEname("员工" + i);
            employee.setSalary(8888f);
            employee.setDname("员工");
            employee.setHiredate(new Date());
            employeeDao.insert(employee);
        }
        //提交事务
        transactionManager.commit(status);
    }catch (RuntimeException e){
        //回滚事务
        transactionManager.rollback(status);
        e.printStackTrace();
    }

}

Spring声明式事务

声明式事务指在不修改源码的情况下通过配置形式自动实现事务控制,声明式事务本质就是AOP环绕通知

当目标方法执行成功是,自动提交事务。目标方法抛出异常时,自动事务回滚

配置过程

  1. 配置TransactionManager事务管理器
  2. 配置事务通知与事务属性
  3. 为事务通知绑定PointCut切点
<!--1. 事务管理器:用于创建事务,提交/回滚-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
</bean>

<!--2. 事务通知配置,决定那些方法使用事务,哪些方法不使用事务-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <!--声明事务的属性-->
    <tx:attributes>
        <!--propagation:事务传播行为-->
        <!--目标方法名为batchImport时,启用声明式事务,成功时提交,运行异常时回滚-->
        <tx:method name="batchImport" propagation="REQUIRED"/>
        <tx:method name="batch*" propagation="REQUIRED"/>
        <!--设置所有find开头的方法不需要使用事务-->
        <tx:method name="find*" propagation="NOT_SUPPORTED" read-only="true"/>
        <tx:method name="get*" propagation="NOT_SUPPORTED" read-only="true"/>
        <!--当前边定义的事务都不符合要求的时候,其他情况到底是否使用声明式事务-->
        <tx:method name="*" propagation="REQUIRED"/>
    </tx:attributes>
</tx:advice>
<!--3. 定义声明式事务的作用范围-->
<aop:config>
    <!--设置切点-->
    <aop:pointcut id="pointCut" expression="execution(* com.imooc..*Service.*(..))"/>
    <!--与txAdvice、pointCut关联-->
    <aop:advisor advice-ref="txAdvice" pointcut-ref="pointCut"/>
</aop:config>

事务传播行为(propagation)

  • 事务传播行为是指多个拥有事务的方法在嵌套调用时的事务控制
  • XML:<tx:method name="..." propagation="REQUIRED"/>
  • 注解:@Transactional(propagation=Propagation.REQUIRED)

image-20220812231506548

注解形式声明事务

<context:component-scan base-package="com.hua"/>
<!--数据源-->
<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/hua?useSSL=false&amp;useUnicode=true&amp;characterEncoding=UTF-8&amp;severTimezone=Asia/Shanghai&amp;allowPublicKeyRetrieval=true"/>
    <property name="username" value="root"/>
    <property name="password" value="123456"/>
</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"/>

https://huauz-1259241435.cos.ap-shanghai.myqcloud.com/blog/202208130016588.png

posted @ 2022-12-02 19:20  与你一起看星辰  阅读(57)  评论(0)    收藏  举报