<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- aop -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.4</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
项目的结构如下:
介绍一下项目的结构的内容:
entity包: 实体类包 。
repository包:数据库repository
service包: 提供服务的service
controller包: 控制器写入用于编写requestMApping 。相关请求的入口类
annotation包: 自定义注解,用于重试 。
aspect包: 用于对自定义注解进行切面 。
DblockApplication: springboot的启动类 。
DblockApplicationTests: 测试类 。
咱们看一下核心代码的实现,参考如下,使用dataJpa非常方便,集成了CrudRepository就可以实现简单的CRUD,非常方便,有兴趣的同学可以自行研究 。
实现乐观锁的方式有两种:
更新的时候将version字段传过来,然后更新的时候就可以进行version判断,如果version可以匹配上,那么就可以更新(方法:updateCatalogWithVersion) 。
在实体类上的version字段上加入version,可以不用自己写SQL语句就可以它就可以自行的按照version匹配和更新,是不是很简单 。
public interface CatalogRepository extends CrudRepository<Catalog, Long> {
@Query(value = https://www.isolves.com/it/sjk/bk/2019-04-08/"select * from Catalog a where a.id = :id for update", nativeQuery = true)
Optional<Catalog> findCatalogsForUpdate(@Param("id") Long id);
@Lock(value = https://www.isolves.com/it/sjk/bk/2019-04-08/LockModeType.PESSIMISTIC_WRITE) //代表行级锁
@Query("select a from Catalog a where a.id = :id")
Optional<Catalog> findCatalogWithPessimisticLock(@Param("id") Long id);
@Modifying(clearAutomatically = true) //修改时需要带上
@Query(value = https://www.isolves.com/it/sjk/bk/2019-04-08/"update Catalog set browse_count = :browseCount, version = version + 1 where id = :id " +
"and version = :version", nativeQuery = true)
int updateCatalogWithVersion(@Param("id") Long id, @Param("browseCount") Long browseCount, @Param("version") Long version);
}
实现悲观锁的时候也有两种方式:
自行写原生SQL,然后写上for update语句 。(方法:findCatalogsForUpdate)
使用@Lock注解,并且设置值为LockModeType.PESSIMISTIC_WRITE即可代表行级锁 。
还有我写的测试类,方便大家进行测试:
package com.hqs.dblock;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = DblockApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class DblockApplicationTests {
@Autowired
private TestRestTemplate testRestTemplate;
@Test
public void browseCatalogTest() {
String url = "http://localhost:8888/catalog";
for(int i = 0; i < 100; i++) {
final int num = i;
new Thread(() -> {
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
params.add("catalogId", "1");
params.add("user", "user" + num);
String result = testRestTemplate.postForObject(url, params, String.class);
System.out.println("-------------" + result);
}
).start();
}
}
@Test
public void browseCatalogTestRetry() {
推荐阅读
- 企业常见5大网络安全问题
- 防御DDoS攻击需要双向解决方案
- Redis 这么火,它都解决了哪些问题?
- 双网卡网络时断时续解决方法
- 化妆品|美容行业九大痛苦现状,如何解决生存之道?
- 离婚前必须清楚的十大问题
- 3招解决安卓机卡慢
- 微信消息延迟不提醒?原来是这2个原因导致的,一招教你解决
- 淘宝违规被限制登录怎么办?限制登录的解决办法 淘宝被限制登录怎么办?限制登录的解决办法
- 手机已连接WiFi但无法访问互联网,是什么问题?
