Spring-TX声明式事务控制

本文详细介绍了Spring框架中的声明式事务控制,包括PlatformTransactionManager接口的使用、TransactionDifinition对象属性、事务传播行为以及实际代码演示。通过UserDao实例,展示了如何在Spring中管理事务,包括PROPAGATION_REQUIRED的事务处理和超时、只读设置。

Spring-TX声明式事务控制

首先我们应该明确不管是哪种框架我们都是实现Spring通过的PlatformTransactionManager接口,这样才能把我们的数据交给Spring管理

Spring中的事物控制API介绍

PlatformTransactionManager接口

  • 获取事务状态信息------------,TransactionStatus getTransaction(TransactionDifinition difinition)
  • 提交事务------------ void commit(TransactionStatus status)
  • 回滚事务-----------void rollback(TransactionDifinition difinition)

TransactionDifinition 事务定义信息对象

  • 获取事务对象名称 String getName()
  • 获取事务的隔离级别 int SgetlsolationLevel()
  • 获取事务的传播行为 int getPropagationBehavior();
  • 获取事务超时时间 int getTimeout();
  • 获取事务是否只读 boolean idReadOnly()

TransactionStatus 事务传播行为

主要解决的就是业务方法进行调用的时候,事务应该如何进行处理

** 保证在同一事物中**

  • PROPAGATION_REQUIRED 支持当前事务, 如果不存在 就新建一个(默认)事务
  • PROPAGATION_SUPPORTS 支持当前事务,如果不存在,就不使用事务。
  • PROPAGATION_MANDATORY 支持当前事务,如果不存在,抛出异常
    保证不在同一事物中
  • PROPAGATION_REQUIRES_NEW 如果有事务存在,挂起当前事务,创建一个新的事务
  • PROPAGATION_NOT_SUPPORTED 以非事务方式运行,如果有事务存在,挂起当前事务
  • PROPAGATION_NEVER 以非事务方式运 行,如果有事务存在,抛出异常
  • PROPAGATION_NESTED 如果当前事务存 在,则嵌套事务执行
    超时时间
    如果没有设定超时时间,默认是没有超时时间限制的默认值为1 如果设置了 单位是秒
    是否只读事务
    对于增删改设定为 false 表示可以操作不限于只读 对于查询操作 设定为true 表示只能读

代码演示

首先写一个pojo实体类
要写成一个javaBean

@Component("user")  //表示交给Spring空间管理
public class User implements Serializable {

    @Value("1")//表示赋值
    private Integer u_id;
    @Value("小孙")//表示赋值
    private String u_name;
    @Value("20")//表示赋值
    private Integer u_age;
    @Value("10000")//表示赋值
    private Double u_salary;

dao接口和他的实现类

public interface UserDao {

    //CRUD

    // 添加用户
    void addUser(User user);
    // 删除用户 根据id值
    void deleteUserById(int uid);
    // 修改用户信息 根据id值
    void updateUserById(User user);
    // 查询所有用户
    List<User> queryAllUsers();
    // 查询单个用户 根据id值
    User queryUserById(int uid);
    // 分页+模糊查询
    List<User> queryFuzzyUserByUsername(String u_name,int beginIndex);
    // 查询总记录值
    int queryUserCount();

}





//实现类
@Repository("userDao")
public class UserDaoImpl implements UserDao {

    @Autowired //前提是Spring容器含有该对象
    private JdbcTemplate jdbcTemplate;

    //Connection  引入数据源奥
    @Autowired
    private DataSource dataSource;

    // 对于数据库来说  增删改 都是更新
    @Override
    public void addUser(User user) {
        Connection connection = null;
        //   在sql执行之前   开启事务
        try {
            //添加用户
            connection = dataSource.getConnection();
            //开启事务
            connection.setAutoCommit(false);   //设置为false  表示开启事务
            PreparedStatement ps = connection.prepareStatement("insert into user values(null,?,?,?)");
            ps.setString(1,user.getU_name());
            ps.setInt(2,user.getU_age());
            ps.setDouble(3,user.getU_salary());
            int num = ps.executeUpdate();
            //进行事务的提交
            //int i = 1/0;  //人造算数异常
            connection.commit();
            if (num > 0) {
                System.out.println("数据添加成功!");
            } else {
                System.out.println("数据添加失败!");
            }

        } catch (Exception e) {
            System.out.println("异常发生了");
            try {
                //有异常信息就回滚
                System.out.println("因为异常,所以数据回滚");
                connection.rollback();
            } catch (Exception throwables) {
                System.out.println("此时添加过程中有异常数据回滚.");
            }
        }


    }

    @Override
    public void deleteUserById(int uid) {
        int num = jdbcTemplate.update("delete from user where u_id = ?", uid);
        if (num > 0) {
            System.out.println("数据删除成功!");
        } else {
            System.out.println("数据删除失败!");
        }
    }

    // 更新用户名和年龄
    @Override
    public void updateUserById(User user) {
        int num = jdbcTemplate.update("update user set u_name = ?,u_age = ? where u_id = ?", user.getU_name(), user.getU_age(), user.getU_id());
        if (num > 0) {
            System.out.println("数据更新成功!");
        } else {
            System.out.println("数据更新失败");
        }
    }

    @Override
    public List<User> queryAllUsers() {
        List<User> users = null;
         try {
             // BeanPropertyRowMapper 装配多条记录
            users = jdbcTemplate.query("select * from user", new BeanPropertyRowMapper<>(User.class));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return users;
    }

    @Override
    public User queryUserById(int uid) {
        // 根据用户id值查询一条记录  queryForObject方法
        User user = null;
        try {
             user = jdbcTemplate.queryForObject("select * from user where u_id = ?", new BeanPropertyRowMapper<>(User.class), uid);
        }catch (Exception e) {
            e.printStackTrace();
        }
        return user;
    }

    // 分页+模糊查询
    @Override
    public List<User> queryFuzzyUserByUsername(String u_name, int beginIndex) {
        List<User> users = null;
        try {
            users = jdbcTemplate.query("select * from user where u_name like '%' ? '%' limit ?,3", new BeanPropertyRowMapper<>(User.class),u_name,beginIndex);
        }catch (Exception e){
            e.printStackTrace();
        }
        return users;
    }

    @Override
    public int queryUserCount() {
        // 需要返回一个数值  queryForObject   后面传入Integer.class字节码对象
        int count = jdbcTemplate.queryForObject("select count(*) from user", Integer.class);
        return count;
    }


}


主配置文件applicationContext.xml


   <!--组件扫描--><!--能扫描到一个包里面全部的类,包下类的自动载入-->
   <context:component-scan base-package="com.zhiyou100"/>

    <!--content:property-->
    <!--引入db.properties文件到Spring容器-->
    <context:property-placeholder location="classpath:db.properties"/>

    <!--配置数据源-->
    <!--采用数据库连接池 C3p0 依赖于数据源DataSource   ComboPooledDataSource  -->
    <!--把ComboPooledDataSource该对象注入到Spring的容器中-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
       <property name="driverClass" value="${jdbc.driverClass}"/>
       <property name="jdbcUrl" value="${jdbc.jdbcUrl}"/>
       <property name="user"  value="${jdbc.user}"/>
       <property name="password" value="${jdbc.password}"/>
    </bean>

   <!--配置JdbcTemplate对象-->
   <!--该对象也依赖于数据源DataSource-->
   <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
       <!--属性注入 采用set方式--><!--后面我们使用的事dataSource-->
       <property name="dataSource" ref="dataSource"/>
       <!-- <constructor-arg -->
   </bean>

db.properties文件和log4j.properties文件

jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.jdbcUrl=jdbc:mysql://localhost:3306/db_spring?characterEncoding=UTF-8
jdbc.user=root
jdbc.password=root


# log4j.properties
# Global logging configuration
log4j.rootLogger=DEBUG, stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

测试类文件

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class JdbcTemplateTest {

    // 进行dao接口的属性注入
    @Autowired //我们之前把  UseDaoImpl注入spring内存管理就是为了这里的属性注入@Repository("userDao")
    private UserDao userDao;

    @Autowired
    private User user;// 此时user值就从容器注入进来

    /**
     * 测试 查询总记录值
     */
    @Test
    public void testQueryCount() {
        int count = userDao.queryUserCount();
        System.out.println(count);// 9
    }

    /**
     * 测试 分页+模糊查询
     */
    @Test
    public void testQueryFuzzyUserByUsername() {
        List<User> users = userDao.queryFuzzyUserByUsername("小", 0);
        for (User user1 : users) {
            System.out.println(user1);
        }
    }

    /**
     *  测试 queryUserById
     */
    @Test
    public void testQueryUserById() {
        // 周八 id值为 7
        User user = userDao.queryUserById(7);
        System.out.println(user);//User{u_id=7, u_name='周八', u_age=29, u_salary=6000.0}
    }

    /**
     * 测试 queryAllUsers
     */
    @Test
    public void testQueryALllUsers(){
        List<User> users = userDao.queryAllUsers();
        for (User user1 : users) {
            System.out.println(user1);
        }
    }

    /**
     * 测试  deleteUser
     */
    @Test
    public void testDeleteUser() {
        userDao.deleteUserById(11);// 数据删除成功!
    }

    /**
     * 测试  updateUser
     */
    @Test
    public void testUpdateUser() {
        // 更新用户名字和年龄 根据id值 --->把小孙的信息更改为小强的信息
        User user = new User();
        user.setU_age(40);
        user.setU_name("小强");
        user.setU_id(11);
        userDao.updateUserById(user);// 数据更新成功!
    }

    /**
     * 测试 addUser
     */
    @Test
    public void testAddUser(){
        userDao.addUser(user);
    }


}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值