3.4 事务管理

93 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第12天,点击查看活动详情

3.4 事务管理

事务管理常见知识

image-20220716070756484

image-20220716071047348

第一类丢失更新

image-20220716073106097

第二类丢失更新

image-20220716073356286

脏读

image-20220716073511481

不可重复读

image-20220716073549458

幻读

image-20220716073736147

不同的隔离级别可以解决的问题

image-20220716074350851

image-20220716074710087

Spring中的事务管理

image-20220716074946222

Spring中的事务管理有两种方式:

  • 声明式事务

    • 通过xml配置,声明某方法的事务特征

    • 通过注解,声明某方法的事务特征

  • 编程式事务

    • 通过 TransactionTemplate 管理事务,并通过它执行数据库的操作。

两者选一种即可,建议选第一种,因为比较简单,当然如果业务比较复杂,仅仅只是想管理一小部分使用第二种

写一个demo演示Spring中的事务管理

1. 声明式事务管理事务

这里我们通过加注解声明某方法的事务特征

@Service
public class AlphaService {
    @Autowired
    private AlphaDao alphaDao;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private DiscussPostMapper discussPostMapper;

    /*
    isolation 事务的隔离级别
    propagation 事务
的传播机制:
        REQUIRED: 支持当前事务(外部事务),如果不存在则创建新事务.
        REQUIRES_NEW: 创建一个新事务,并且暂停当前事务(外部事务).
        NESTED: 如果当前存在事务(外部事务),则嵌套在该事务中执行(独立的提交和回滚),不存在外部事务就会和REQUIRED一样
     */
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED)
    public Object save1(){
        // 新增用户
        User user = new User();
        user.setUsername("alpha");
        user.setSalt(CommunityUtil.generateUUID().substring(0, 5));
        user.setPassword(CommunityUtil.md5("123" + user.getSalt()));
        user.setEmail("alpha@qq.com");
        user.setHeaderUrl("http://image.nowcoder.com/head/99t.png");
        user.setCreateTime(new Date());
        userMapper.insertUser(user);

        // 新增帖子
        DiscussPost post = new DiscussPost();
        post.setUserId(user.getId());         // 虽然上面我们没有给user设置id,但是执行过数据库操作之后,数据库给user的id
        post.setTitle("Hello");
        post.setContent("新人报道!");
        post.setCreateTime(new Date());
        discussPostMapper.insertDiscussPost(post);

        // 报错
        Integer.valueOf("abc");         // 将 "abc" 这个字符串转换为整数,肯定转不了,报错

        return "ok";
    }
}

image-20220716084142050

测试:

@RunWith(SpringRunner.class)
@SpringBootTest
@ContextConfiguration(classes = CommunityApplication.class)
public class TransactionTests {

    @Autowired
    private AlphaService alphaService;

    @Test
    public void testSave1() {
        Object obj = alphaService.save1();
        System.out.println(obj);
    }

}

image-20220716084645109

2. 编程式事务管理

通过 TransactionTemplate 管理事务

@Service
public class AlphaService {
    @Autowired
    private AlphaDao alphaDao;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private DiscussPostMapper discussPostMapper;

    /*
    这个类是Spring自动创建的,我们无须配置,直接注入即可
    */
    @Autowired
    private TransactionTemplate transactionTemplate;

    public Object save2(){
        transactionTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);  // 设置隔离级别
        transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); // 设置传播机制

        return transactionTemplate.execute(new TransactionCallback<Object>() {

            @Override
            public Object doInTransaction(TransactionStatus status) {
                // 新增用户
                User user = new User();
                user.setUsername("beta");
                user.setSalt(CommunityUtil.generateUUID().substring(0, 5));
                user.setPassword(CommunityUtil.md5("123" + user.getSalt()));
                user.setEmail("beta@qq.com");
                user.setHeaderUrl("http://image.nowcoder.com/head/999t.png");
                user.setCreateTime(new Date());
                userMapper.insertUser(user);

                // 新增帖子
                DiscussPost post = new DiscussPost();
                post.setUserId(user.getId());
                post.setTitle("你好");
                post.setContent("我是新人!");
                post.setCreateTime(new Date());
                discussPostMapper.insertDiscussPost(post);

                Integer.valueOf("abc");

                return "ok";
            }
        });
    }
}

image-20220716090819431

测试:

@RunWith(SpringRunner.class)
@SpringBootTest
@ContextConfiguration(classes = CommunityApplication.class)
public class TransactionTests {

    @Autowired
    private AlphaService alphaService;

    @Test
    public void testSave2() {
        Object obj = alphaService.save2();
        System.out.println(obj);
    }

}

image-20220716091005794