Spring data Jpa,Mybatis,读写锁,@Lock 使用

Spring data jpa 支持注解式的读写锁(悲观锁),实际上这个东西硬编码也简单,但是基于Jpa 命名方式定义的Sql,只能用注解添加支持读写锁了,

不了解读写锁的可以点这里

mysql读写锁及事务

并且推荐

PESSIMISTIC_READ,PESSIMISTIC_WRITE,而不是
READ,WRITE,但是官方文档貌似没有更新这个案例,踩了一些坑.

新建一个实体Book.java

/**
 * User: laizhenwei
 * Date: 2018-04-18 Time: 9:04
 * Description:
 */
@Entity
@Table(name = "test_book")
@Alias("Book")
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class Book extends AbstractJbatisIdEntity{

    private static final long serialVersionUID = -1L;

    private String name;

    private String author;

}
BookRepository.java
/**
 * User: laizhenwei
 * Date: 2018-04-18 Time: 9:11
 * Description:
 */
public interface BookRepository extends JpaRepository<Book,String> {
    @Lock(LockModeType.PESSIMISTIC_READ)
    Book findTop1ByName(String name);
}
BookServiceImpl TimeUnit.SECONDS.sleep(20); 是为了让事务延迟提交,好测试save操作需要阻塞到读写释放才能提交
    public static final  CountDownLatch readCount = new CountDownLatch(1);
    public static final  CountDownLatch saveCount = new CountDownLatch(1);

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    @Override
    public Book save(Book book){
        Book book1 = null;
        try {
            readCount.await();
            book1 = getRepository().save(book);
            saveCount.countDown();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return book1;
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    @Override
    public Book findTop1ByName(String name){
        Book book = getRepository().findTop1ByName(name);
        try {
            readCount.countDown();
            TimeUnit.SECONDS.sleep(20);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return book;
    }

JunitTest 先添加一条数据,待会要锁这个数据

    @Test
    public void save(){
        Book book = new Book();
        book.setName("百年孤独");
        book.setAuthor("加西亚·马尔克斯");
        bookRepository.save(book);
    }

开启两条线程,一条先加上读锁,然后睡眠一会,另一条线程去修改这个对象的时候,需要阻塞到读事务提交以后才会成功

第二个查询动作不会阻塞,因为读锁只对写操作限制(这里用直接用bookRepository,是为了避免CountDownLatch 再一次阻塞而已)

    @Test
    @Transactional
    public void findByName() throws InterruptedException {

        new Thread(()->bookService.findTop1ByName("百年孤独")).start();
        BookServiceImpl.readCount.await();
        Book book =bookRepository.findTop1ByName("百年孤独");

        book.setAuthor("加西亚·马尔克斯5");
        new Thread(()->bookService.save(book)).start();
        BookServiceImpl.saveCount.await();

    }

有个有趣的现象,如果直接运行第二次,会发现不用阻塞,就能save成功,因为数据并没有做任何修改.

再注释掉@Lock跑一次,修改 book.setAuthor("加西亚·马尔克斯5");再保存也不需要等待.

Mybatis下的实现,就是手动编码而已

/**
 * User: laizhenwei
 * Date: 2018-04-18 Time: 9:12
 */
@Mapper
public interface BookMapper extends BaseMapper<Book> {

    @Select("select * from test_book where name=#{name} limit 1 lock in share mode")
    Book findTop1ByName(String name);

}

Service  TimeUnit.SECONDS.sleep(20); 是为了让事务延迟提交,好测试save操作需要阻塞到读写释放才能提交

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    @Override
    public Book mapperFindTop1ByName(String name){
        Book book = getMapper().findTop1ByName(name);
        try {
            readCount.countDown();
            TimeUnit.SECONDS.sleep(20);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return book;
    }

JunitTest (这里用直接用bookRepository,是为了避免CountDownLatch 再一次阻塞而已)

    @Test
    @Transactional
    public void findByName() throws InterruptedException {

        new Thread(()->bookService.mapperFindTop1ByName("百年孤独")).start();
        BookServiceImpl.readCount.await();
        Book book =bookRepository.findTop1ByName("百年孤独"); 

        book.setAuthor("加西亚·马尔克斯3");
        new Thread(()->bookService.save(book)).start();
        BookServiceImpl.saveCount.await();

    }

测试效果与Jpa一样.

原文地址:https://www.cnblogs.com/sweetchildomine/p/8874731.html

时间: 2024-11-07 08:37:05

Spring data Jpa,Mybatis,读写锁,@Lock 使用的相关文章

Spring Data JPA、 MyBatis与Hibernate简单对比

整体参考: https://blog.csdn.net/xihuanyuye/article/details/81201441 详细参考: https://blog.csdn.net/qq897958555/article/details/53208002 1.Spring Data JPA与Hibernate Spring Data JPA是Spring Data的子模块.使用Spring Data,使得基于“repositories”概念的JPA实现更简单和容易.Spring Data JP

Hibernate、Mybatis与Spring Data JPA的区别

1.概念: Hibernate:Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库.属于全自动的ORM框架,着力点在于POJO和数据库表之间的映射,完成映射即可自动生成和执行sql. Mybatis:MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis .

Spring Data JPA 和MyBatis比较

两种框架自己都用过一段时间,现在想总结一下各自适用的场景,部分比较取自群友分享 框架简介 Spring Data JPA是Spring Data的子模块.使用Spring Data,使得基于“repositories”概念的JPA实现更简单和容易.Spring Data JPA的目标是大大简化数据访问层代码的编码.作为使用者,我们只需要编写自己的repository接口,接口中包含一些个性化的查询方法,Spring Data JPA将自动实现查询方法.JPA默认使用hibernate作为ORM实

Spring Data Jpa系列教程--------实体解析和关联关系

Spring Data Jpa是基于HIbernate开发的,所以建立实体建的实体和映射关系需要好好好的去了解一下,本文有以下内容,实体管理器介绍,实体与数据库表的映射介绍,关联关系(一对多,多对多)介绍,SpringDataJpa应用分析 ------实体管理器   实体管理器EntityManager是实体与数据库的桥梁(和事务一起发挥作用),相当于Hibenrtae中的session,Mybatis中的sqlSession.使用方法放个小例子吧 @PersistenceContext pr

Spring Data JPA进阶——Specifications和Querydsl

Spring Data JPA进阶--Specifications和Querydsl 本篇介绍一下Spring Data JPA中能为数据访问程序的开发带来更多便利的特性,我们知道,Spring Data repository的配置很简单,一个典型的repository像下面这样: public interface CustomerRepository extends JpaRepository<Customer, Long> { Customer findByEmailAddress(Str

JavaEE 之 Spring Data JPA

1.事务 a.事务的关键属性(ACID) ①原子性(atomicity):事务的原子性确保动作要么全部完成,要么完全不起作用 ②一致性(consistency):一旦所有事务动作完成,事务就被提交.也就是说要么都成功,要么都不成功 ③隔离性(isolation):多个事物同时处理一个数据的时候,每个事物都应该与其他事务隔离开来,防止数据损坏 ④持久性(durability):一旦事务完成,无论发生什么系统错误,它的结果都不应该受到影响.应该被持久化到数据库中 b.事务的传播行为 ①REQUERE

spring boot + spring data jpa

Spring Data Repository的核心接口是Repository(好像也没什么好惊讶的).这个接口需要领域类(Domain Class)跟领域类的ID类型作为参数.这个接口主要是让你能知道继承这个类的接口的类型.CrudRepository 供了对被管理的实体类的一些常用CRUD方法. 2. springboot 整合spring data jpa 默认你已经构建好了spring boot 项目,关于spring boot项目的新建,请参考: springboot Demo spri

Spring Data JPA(官方文档翻译)

关于本书 介绍 关于这本指南 第一章 前言 第二章 新增及注意点 第三章 项目依赖 第四章 使用Spring Data Repositories 4.1 核心概念 4.2 查询方法 4.3 定义repository的接口 4.4 定义查询方法 4.5. 创建repository实例 Spring Data JPA 参考指南 中文版 阅读地址: https://www.gitbook.com/book/ityouknow/spring-data-jpa-reference-documentatio

Spring Data JPA 的作用.

在JPA规范基础下提供了 Repository 层的实现 , 能够方便大家在不同的ORM框架之间进行切换而不要更改代码 . PS : 我们用不同的ORM框架 , 在DAO层写业务代码会稍微有差异 , SpringDataJPA 就是为了解决这个出现的. JPA(Java Persistence API)是Sun官方提出的Java持久化规范.它为Java开发人员提供了一种对象/关联映射工具来管理Java应用中的关系数据.它的出现主要是为了简化现有的持久化开发工作和整合ORM技术结束Hibernat