您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > JAVA

SpringBoot事物Transaction实战讲解教程

时间:2019-08-30 09:03:41  来源:  作者:

前言

本篇文章主要介绍的是SpringBoot的事物Transaction使用的教程。

SpringBoot Transaction

说明:如果想直接获取工程那么可以直接跳到底部,通过链接下载工程代码。

Transaction

事务管理方式

在Spring中,事务有两种实现方式,分别是编程式事务管理和声明式事务管理两种方式。

  • 编程式事务管理: 编程式事务管理使用TransactionTemplate或者直接使用底层的PlatformTransactionManager。对于编程式事务管理,spring推荐使用TransactionTemplate。
  • 声明式事务管理: 建立在AOP之上的。其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。
  • 声明式事务管理不需要入侵代码,通过@Transactional就可以进行事务操作,更快捷而且简单,推荐使用。

事务提交方式

默认情况下,数据库处于自动提交模式。每一条语句处于一个单独的事务中,在这条语句执行完毕时,如果执行成功则隐式的提交事务,如果执行失败则隐式的回滚事务。

对于正常的事务管理,是一组相关的操作处于一个事务之中,因此必须关闭数据库的自动提交模式。不过,这个我们不用担心,spring会将底层连接的自动提交特性设置为false。也就是在使用spring进行事物管理的时候,spring会将是否自动提交设置为false,等价于JDBC中的 connection.setAutoCommit(false);,在执行完之后在进行提交,connection.commit(); 。

事务隔离级别

隔离级别是指若干个并发的事务之间的隔离程度。TransactionDefinition 接口中定义了五个表示隔离级别的常量:

  • TransactionDefinition.ISOLATION_DEFAULT:这是默认值,表示使用底层数据库的默认隔离级别。对大部分数据库而言,通常这值就是TransactionDefinition.ISOLATION_READ_COMMITTED。
  • TransactionDefinition.ISOLATION_READ_UNCOMMITTED:该隔离级别表示一个事务可以读取另一个事务修改但还没有提交的数据。该级别不能防止脏读,不可重复读和幻读,因此很少使用该隔离级别。比如PostgreSQL实际上并没有此级别。
  • TransactionDefinition.ISOLATION_READ_COMMITTED:该隔离级别表示一个事务只能读取另一个事务已经提交的数据。该级别可以防止脏读,这也是大多数情况下的推荐值。
  • TransactionDefinition.ISOLATION_REPEATABLE_READ:该隔离级别表示一个事务在整个过程中可以多次重复执行某个查询,并且每次返回的记录都相同。该级别可以防止脏读和不可重复读。
  • TransactionDefinition.ISOLATION_SERIALIZABLE:所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。

事务传播行为

所谓事务的传播行为是指,如果在开始当前事务之前,一个事务上下文已经存在,此时有若干选项可以指定一个事务性方法的执行行为。在TransactionDefinition定义中包括了如下几个表示传播行为的常量:

  • TransactionDefinition.PROPAGATION_REQUIRED:如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。这是默认值。
  • TransactionDefinition.PROPAGATION_REQUIRES_NEW:创建一个新的事务,如果当前存在事务,则把当前事务挂起。
  • TransactionDefinition.PROPAGATION_SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
  • TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事务方式运行,如果当前存在事务,则把当前事务挂起。
  • TransactionDefinition.PROPAGATION_NEVER:以非事务方式运行,如果当前存在事务,则抛出异常。
  • TransactionDefinition.PROPAGATION_MANDATORY:如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。
  • TransactionDefinition.PROPAGATION_NESTED:如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED。

事务回滚规则

指示spring事务管理器回滚一个事务的推荐方法是在当前事务的上下文内抛出异常。spring事务管理器会捕捉任何未处理的异常,然后依据规则决定是否回滚抛出异常的事务。

默认配置下,spring只有在抛出的异常为运行时unchecked异常时才回滚该事务,也就是抛出的异常为RuntimeException的子类(Errors也会导致事务回滚),而抛出checked异常则不会导致事务回滚。

可以明确的配置在抛出那些异常时回滚事务,包括checked异常。也可以明确定义那些异常抛出时不回滚事务。

事务常用配置

  • readOnly:该属性用于设置当前事务是否为只读事务,设置为true表示只读,false则表示可读写,默认值为false。例如:@Transactional(readOnly=true);
  • rollbackFor: 该属性用于设置需要进行回滚的异常类数组,当方法中抛出指定异常数组中的异常时,则进行事务回滚。例如:指定单一异常类:@Transactional(rollbackFor=RuntimeException.class)指定多个异常类:@Transactional(rollbackFor={RuntimeException.class, Exception.class});
  • rollbackForClassName: 该属性用于设置需要进行回滚的异常类名称数组,当方法中抛出指定异常名称数组中的异常时,则进行事务回滚。例如:指定单一异常类名称@Transactional(rollbackForClassName=”RuntimeException”)指定多个异常类名称:@Transactional(rollbackForClassName={“RuntimeException”,”Exception”})。
  • noRollbackFor:该属性用于设置不需要进行回滚的异常类数组,当方法中抛出指定异常数组中的异常时,不进行事务回滚。例如:指定单一异常类:@Transactional(noRollbackFor=RuntimeException.class)指定多个异常类:@Transactional(noRollbackFor={RuntimeException.class, Exception.class})。
  • noRollbackForClassName:该属性用于设置不需要进行回滚的异常类名称数组,当方法中抛出指定异常名称数组中的异常时,不进行事务回滚。例如:指定单一异常类名称:@Transactional(noRollbackForClassName=”RuntimeException”)指定多个异常类名称:@Transactional(noRollbackForClassName={“RuntimeException”,”Exception”})。
  • propagation : 该属性用于设置事务的传播行为。例如:@Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true)。
  • isolation:该属性用于设置底层数据库的事务隔离级别,事务隔离级别用于处理多事务并发的情况,通常使用数据库的默认隔离级别即可,基本不需要进行设置。
  • timeout:该属性用于设置事务的超时秒数,默认值为-1表示永不超时。

事物注意事项

  1. 要根据实际的需求来决定是否要使用事物,最好是在编码之前就考虑好,不然到以后就难以维护;
  2. 如果使用了事物,请务必进行事物测试,因为很多情况下以为事物是生效的,但是实际上可能未生效!
  3. 事物@Transactional的使用要放再类的公共(public)方法中,需要注意的是在 protected、private 方法上使用 @Transactional 注解,它也不会报错(IDEA会有提示),但事务无效。
  4. 事物@Transactional是不会对该方法里面的子方法生效!也就是你在公共方法A声明的事物@Transactional,但是在A方法中有个子方法B和C,其中方法B进行了数据操作,但是该异常被B自己处理了,这样的话事物是不会生效的!反之B方法声明的事物@Transactional,但是公共方法A却未声明事物的话,也是不会生效的!如果想事物生效,需要将子方法的事务控制交给调用的方法,在子方法中使用rollbackFor注解指定需要回滚的异常或者将异常抛出交给调用的方法处理。一句话就是在使用事物的时候子方法最好将异常抛出!
  5. 事物@Transactional由spring控制的时候,它会在抛出异常的时候进行回滚。如果自己使用catch捕获了处理了,是不生效的,如果想生效可以进行手动回滚或者在catch里面将异常抛出,比如throw new RuntimeException();。

开发准备

环境要求

JDK:1.8

SpringBoot:1.5.17.RELEASE

首先还是Maven的相关依赖:

pom.xml文件如下:

 <properties>
 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 <JAVA.version>1.8</java.version>
 <maven.compiler.source>1.8</maven.compiler.source>
 <maven.compiler.target>1.8</maven.compiler.target>
 </properties>
 <parent>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-parent</artifactId>
 <version>1.5.17.RELEASE</version>
 <relativePath /> 
 </parent>
 <dependencies>
 <!-- Spring Boot Web 依赖 核心 -->
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-web</artifactId>
 </dependency>
 <!-- Spring Boot Test 依赖 -->
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-test</artifactId>
 <scope>test</scope>
 </dependency>
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-devtools</artifactId>
 <optional>true</optional>
 </dependency>
 <dependency>
 <groupId>org.mybatis.spring.boot</groupId>
 <artifactId>mybatis-spring-boot-starter</artifactId>
 <version>1.2.0</version>
 </dependency>
 <!-- MySQL 连接驱动依赖 -->
 <dependency>
 <groupId>mysql</groupId>
 <artifactId>mysql-connector-java</artifactId>
 <version>5.1.44</version>
 </dependency>
 <!-- Druid 数据连接池依赖 -->
 <dependency>
 <groupId>com.alibaba</groupId>
 <artifactId>druid</artifactId>
 <version>1.1.8</version>
 </dependency>
 </dependencies>

Application.properties的文件的配置:

banner.charset=UTF-8
server.Tomcat.uri-encoding=UTF-8
spring.http.encoding.charset=UTF-8
spring.http.encoding.enabled=true
spring.http.encoding.force=true
spring.messages.encoding=UTF-8
spring.application.name=springboot-transactional
server.port=8182
spring.datasource.url=jdbc:mysql://localhost:3306/springBoot?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.initialSize=5
spring.datasource.minIdle=5
spring.datasource.maxActive=20
spring.datasource.maxWait=60000
spring.datasource.timeBetweenEvictionRunsMillis=60000
spring.datasource.minEvictableIdleTimeMillis=300000
spring.datasource.validationQuery=SELECT 1 FROM DUAL
spring.datasource.testWhileIdle=true
spring.datasource.testOnBorrow=false
spring.datasource.testOnReturn=false
spring.datasource.poolPreparedStatements=true
spring.datasource.maxPoolPreparedStatementPerConnectionSize=20
spring.datasource.filters=stat,wall,log4j
spring.datasource.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
logging.level.com.pancm.dao=debug

代码编写

SpringBoot在使用事物Transactional的时候,要在main方法上加上 @EnableTransactionManagement 注解开发事物声明,在使用的service层的公共方法加上 @Transactional (spring)注解。

使用示例一

那么首先我们来看下 @Transactional 这个注解的使用方法吧,只需要你在需要添加公共方法上面添加该注解即可。但是这么使用的话需要你将异常抛出,由spring进行去控制。

代码示例:

 @Transactional
 public boolean test1(User user) throws Exception {
 long id = user.getId();
 System.out.println("查询的数据1:" + udao.findById(id));
 // 新增两次,会出现主键ID冲突,看是否可以回滚该条数据
 udao.insert(user);
 System.out.println("查询的数据2:" + udao.findById(id));
 udao.insert(user);
 return false;
 }

使用示例二

如果我们在使用事物 @Transactional 的时候,想自己对异常进行处理的话,那么我们可以进行手动回滚事物。在catch中加上 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); 方法进行手动回滚。不过需要注意的是发生异常需要第一时间进行手动回滚事物,也就是要在异常抛出之前!

代码示例:

 @Transactional
 public boolean test2(User user) {
 long id = user.getId();
 try {
 System.out.println("查询的数据1:" + udao.findById(id));
 // 新增两次,会出现主键ID冲突,看是否可以回滚该条数据
 udao.insert(user);
 System.out.println("查询的数据2:" + udao.findById(id));
 udao.insert(user);
 } catch (Exception e) {
 System.out.println("发生异常,进行手动回滚!");
 // 手动回滚事物
 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
 e.printStackTrace();
 }
 return false;
 }

使用示例三

如果我们在使用事物 @Transactional 的时候,调用了其他的子方法进行了数据库的操作,但是我们想使其事物生效的话,我们可以使用rollbackFor注解或者将该子方法的异常抛出由调用的方法进行处理,不过这里需要注意的是,子方法也必须是公共的方法!

代码示例:

@Transactional
 public boolean test3(User user) {
 /*
 * 子方法出现异常进行回滚
 */
 try {
 System.out.println("查询的数据1:" + udao.findById(user.getId()));
 deal1(user);
 deal2(user);
 deal3(user);
 } catch (Exception e) {
 System.out.println("发生异常,进行手动回滚!");
 // 手动回滚事物
 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
 e.printStackTrace();
 } 
 return false;
 }
 public void deal1(User user) throws SQLException {
 udao.insert(user);
 System.out.println("查询的数据2:" + udao.findById(user.getId()));
 }
 public void deal2(User user) throws SQLException{
 if(user.getAge()<20){
 //SQL异常
 udao.insert(user);
 }else{
 user.setAge(21);
 udao.update(user);
 System.out.println("查询的数据3:" + udao.findById(user.getId()));
 }
 }
 @Transactional(rollbackFor = SQLException.class)
 public void deal3(User user) {
 if(user.getAge()>20){
 //SQL异常
 udao.insert(user);
 }
 }

使用示例四

如果我们不想使用事物 @Transactional 注解,想自己进行事物控制(编程事物管理),控制某一段的代码事物生效,但是又不想自己去编写那么多的代码,那么可以使用springboot中的DataSourceTransactionManager和TransactionDefinition这两个类来结合使用,能够达到手动控制事物的提交回滚。不过在进行使用的时候,需要注意在回滚的时候,要确保开启了事物但是未提交,如果未开启或已提交的时候进行回滚是会在catch里面发生异常的!

代码示例:

 @Autowired
 private DataSourceTransactionManager dataSourceTransactionManager;
 @Autowired
 private TransactionDefinition transactionDefinition;
 public boolean test4(User user) {
 /*
 * 手动进行事物控制
 */
 TransactionStatus transactionStatus=null;
 boolean isCommit = false;
 try {
 transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
 System.out.println("查询的数据1:" + udao.findById(user.getId()));
 // 进行新增/修改
 udao.insert(user);
 System.out.println("查询的数据2:" + udao.findById(user.getId()));
 if(user.getAge()<20) {
 user.setAge(user.getAge()+2);
 udao.update(user);
 System.out.println("查询的数据3:" + udao.findById(user.getId()));
 }else {
 throw new Exception("模拟一个异常!");
 }
 //手动提交
 dataSourceTransactionManager.commit(transactionStatus);
 isCommit= true;
 System.out.println("手动提交事物成功!");
 throw new Exception("模拟第二个异常!");
 } catch (Exception e) {
 //如果未提交就进行回滚
 if(!isCommit){
 System.out.println("发生异常,进行手动回滚!");
 //手动回滚事物
 dataSourceTransactionManager.rollback(transactionStatus);
 }
 e.printStackTrace();
 }
 return false;
 }

上述的这几种示例是比较常见使用的,基本可以满足日常我们对事物的使用,spring里面还有一种事物的控制方法,就是设置断点进行回滚。但是这种方法个人还没实际验证过,可靠性待确认。

使用方法如下:

 Object savePoint =null;
 try{
 //设置回滚点
 savePoint = TransactionAspectSupport.currentTransactionStatus().createSavepoint();
 }catch(Exception e){
 //出现异常回滚到savePoint。
 TransactionAspectSupport.currentTransactionStatus().rollbackToSavepoint(savePoint);
 }

上面的使用示例介绍完毕之后,我们再来介绍一下几个主要的类。

首先还是实体类:

实体类

又是万能的用户表

 public class User {
 
 private Long id;
 
 private String name;
 
 private Integer age;
 
 //getter 和 setter 略
 
 }

Controller 控制层

然后便是控制层,控制层这块的我做了下最后的查询,用于校验事物是否成功生效!

控制层代码如下:

 @RestController
 @RequestMapping(value = "/api/user")
 public class UserRestController {
 
 @Autowired
 private UserService userService;
 
 @Autowired
 private UserDao userDao;
 
 
 @PostMapping("/test1")
 public boolean test1(@RequestBody User user) {
 System.out.println("请求参数:" + user);
 try {
 userService.test1(user);
 } catch (Exception e) {
 // TODO Auto-generated catch block
 e.printStackTrace();
 }
 System.out.println("最后查询的数据:" + userDao.findById(user.getId()));
 return true;
 }
 
 @PostMapping("/test2")
 public boolean test2(@RequestBody User user) { 
 System.out.println("请求参数:" + user);
 userService.test2(user);
 System.out.println("最后查询的数据:" + userDao.findById(user.getId()));
 return true;
 }
 
 @PostMapping("/test3")
 public boolean test3(@RequestBody User user) { 
 System.out.println("请求参数:" + user);
 userService.test3(user);
 System.out.println("最后查询的数据:" + userDao.findById(user.getId()));
 return true;
 }
 
 @PostMapping("/test4")
 public boolean test4(@RequestBody User user) { 
 System.out.println("请求参数:" + user);
 userService.test4(user);
 System.out.println("最后查询的数据:" + userDao.findById(user.getId()));
 return true;
 }
 }

App 入口

和普通的SpringBoot项目基本一样,只不过需要加上 @EnableTransactionManagement 注解!

代码如下:

 @EnableTransactionManagement
 @SpringBootApplication
 public class TransactionalApp
 {
 
 public static void main( String[] args )
 {
 SpringApplication.run(TransactionalApp.class, args);
 System.out.println("Transactional 程序正在运行...");
 
 }
 }

功能测试

我们在启动程序之后,来进行上述的几个示例测试,这里的测试示例分别对应上述的使用示例,有的示例需要测试两边以上才能验证事物是否能够生效!这里我们使用Postman进行测试!

测试示例一

两次测试,第一次不使用@Transactional注解,第二次使用!

第一次测试:

注释掉@Transactional注解!

使用进行POST请求

http://localhost:8182/api/user/test1

Body参数为:

{"id":1,"name":"xuwujing","age":18}

控制台打印的数据:

 请求参数:User [id=1, name=xuwujing, age=18]
 查询的数据1:null
 查询的数据2:User [id=1, name=xuwujing, age=18]
 Duplicate entry '1' for key 'PRIMARY'
 最后查询的数据:User [id=1, name=xuwujing, age=18]

第二次测试:

解除@Transactional注解注释!

使用进行POST请求

http://localhost:8182/api/user/test1

Body参数为:

{"id":1,"name":"xuwujing","age":18}

控制台打印的数据:

 请求参数:User [id=1, name=xuwujing, age=18]
 查询的数据1:null
 查询的数据2:User [id=1, name=xuwujing, age=18]
 Duplicate entry '1' for key 'PRIMARY'
 最后查询的数据:null

注: 在第二次测试的之前是把第一次测试写入数据库的id为1的数据个删除了!

第一次测试中由于没有添加@Transactional注解,因此发生了异常数据还是写入了,但是第二次测试中添加了@Transactional注解,发现即使数据已经写入了,但是出现了异常之后,数据最终被回滚了,没有写入!

从上述的测试用例中可以看到测试用例一种的事物已经生效了!

测试示例二

由于使用示例二中的代码几乎和使用示例一种的一样,不同的是异常由我们自己进行控制!

使用进行POST请求

http://localhost:8182/api/user/test2

Body参数为:

{"id":1,"name":"xuwujing","age":18}

控制台打印的数据:

 请求参数:User [id=1, name=xuwujing, age=18]
 查询的数据1:null
 查询的数据2:User [id=1, name=xuwujing, age=18]
 发生异常,进行手动回滚!
 Duplicate entry '1' for key 'PRIMARY'
 最后查询的数据:null

可以看到事物生效了!

测试示例三

由于使用示例三中进行了子方法调用,这里我们进行两次测试,根据不同的请求条件来进行测试!

第一次测试:

使用进行POST请求

http://localhost:8182/api/user/test3

Body参数为:

{"id":1,"name":"xuwujing","age":18}

控制台打印的数据:

 请求参数:User [id=1, name=xuwujing, age=18]
 查询的数据1:null
 查询的数据2:User [id=1, name=xuwujing, age=18]
 发生异常,进行手动回滚!
 Duplicate entry '1' for key 'PRIMARY'
 最后查询的数据:null

第二次测试:

使用进行POST请求

http://localhost:8182/api/user/test3

Body参数为:

{"id":1,"name":"xuwujing","age":21}

控制台打印的数据:

 请求参数:User [id=1, name=xuwujing, age=21]
 查询的数据1:null
 查询的数据2:User [id=1, name=xuwujing, age=21]
 查询的数据3:User [id=1, name=xuwujing2, age=21]
 发生异常,进行手动回滚!
 Duplicate entry '1' for key 'PRIMARY'
 最后查询的数据:null

根据上述的两次测试,可以得出使用rollbackFor注解或者将该子方法的异常抛出由调用的方法进行处理都可以使事物生效!

测试示例四

由于使用示例四中进行了手动控制事物,这里我们进行两次测试,根据不同的请求条件来进行测试!

第一次测试:

使用进行POST请求

http://localhost:8182/api/user/test4

Body参数为:

{"id":1,"name":"xuwujing","age":18}

控制台打印的数据:

 请求参数:User [id=1, name=xuwujing, age=18]
 查询的数据1:null
 查询的数据2:User [id=1, name=xuwujing, age=18]
 查询的数据3:User [id=1, name=xuwujing2, age=20]
 手动提交事物成功!
 模拟第二个异常!
 最后查询的数据:User [id=1, name=xuwujing, age=20]

第二次测试:

事先还是把数据库id为1的数据给删除!

使用进行POST请求

http://localhost:8182/api/user/test4

Body参数为:

{"id":1,"name":"xuwujing","age":21}

控制台打印的数据:

 请求参数:User [id=1, name=xuwujing, age=21]
 查询的数据1:null
 查询的数据2:User [id=1, name=xuwujing, age=21]
 发生异常,进行手动回滚!
 模拟一个异常!
 最后查询的数据:null

根据上述的两次测试,我们可以得出使用手动控制事物完全ok,只要提交了事物,即使后面发生了异常也不回影响之前的写入!如果在控制的范围之类发生了异常,也可以进行回滚!

测试示例图:

SpringBoot事物Transaction实战讲解教程

 


SpringBoot事物Transaction实战讲解教程

 

来源:https://www.cnblogs.com/xuwujing/p/11184162.html



Tags:SpringBoot   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
我是一名程序员关注我们吧,我们会多多分享技术和资源。进来的朋友,可以多了解下青锋的产品,已开源多个产品的架构版本。Thymeleaf版(开源)1、采用技术: springboot、layui、Thymel...【详细内容】
2021-12-14  Tags: SpringBoot  点击:(21)  评论:(0)  加入收藏
前言项目中的配置文件会有密码的存在,例如数据库的密码、邮箱的密码、FTP的密码等。配置的密码以明文的方式暴露,并不是一种安全的方式,特别是大型项目的生产环境中,因为配置文...【详细内容】
2021-11-17  Tags: SpringBoot  点击:(25)  评论:(0)  加入收藏
SpringBoot开发的物联网通信平台系统项目功能模块 功能 说明 MQTT 1.SSL支持 2.集群化部署时暂不支持retain&will类型消 UDP ...【详细内容】
2021-11-05  Tags: SpringBoot  点击:(56)  评论:(0)  加入收藏
1. 介绍1.1 介绍今天开始我们来学习Java操作MySQL数据库的技巧,Java操作MySQL是借助JdbcTemplate这个对象来实现的。JdbcTemplate是一个多数据库集中解决方案,而我们今天只讲...【详细内容】
2021-11-05  Tags: SpringBoot  点击:(30)  评论:(0)  加入收藏
SpringBoot中的Controller注册本篇将会以Servlet为切入点,通过源码来看web容器中的Controller是如何注册到HandlerMapping中。请求来了之后,web容器是如何根据请求路径找到对...【详细内容】
2021-11-04  Tags: SpringBoot  点击:(53)  评论:(0)  加入收藏
环境:Springboot2.4.11环境配置接下来的演示都是基于如下接口进行。@RestController@RequestMapping("/exceptions")public class ExceptionsController { @GetMapping(...【详细内容】
2021-10-11  Tags: SpringBoot  点击:(41)  评论:(0)  加入收藏
SpringBoot项目默认使用logback, 已经内置了 logback 的相关jar包,会从resource包下查找logback.xml, logback 文件格式范本 可直接复制使用,有控制台 info.log error.log三个...【详细内容】
2021-10-09  Tags: SpringBoot  点击:(50)  评论:(0)  加入收藏
环境:Springboot2.4.10当应用程序启动时,Spring Boot将自动从以下位置查找并加载application.properties和application.yaml文件: 从Classpath类路径classpath的根类路径classp...【详细内容】
2021-09-26  Tags: SpringBoot  点击:(78)  评论:(0)  加入收藏
搭建基础1. Intellij IDEA 2. jdk1.8 3. maven3.6.3搭建方式(1)在线创建项目Spring Boot 官方提供的一种创建方式,在浏览器中访问如下网址: https://start.spring.io/在打开的页...【详细内容】
2021-09-14  Tags: SpringBoot  点击:(78)  评论:(0)  加入收藏
最近开发项目的时候需要用到对象的属性拷贝,以前也有用过一些复制框架,比如spring的 BeanUtils.copyProperties等方式,但总是不尽如人意,最近发现使用orika进行对象拷贝挺好用的...【详细内容】
2021-08-27  Tags: SpringBoot  点击:(232)  评论:(0)  加入收藏
▌简易百科推荐
面向对象的特征之一封装 面向对象的特征之二继承 方法重写(override/overWrite) 方法的重载(overload)和重写(override)的区别: 面向对象特征之三:多态 Instanceof关键字...【详细内容】
2021-12-28  顶顶架构师    Tags:面向对象   点击:(2)  评论:(0)  加入收藏
一、Redis使用过程中一些小的注意点1、不要把Redis当成数据库来使用二、Arrays.asList常见失误需求:把数组转成list集合去处理。方法:Arrays.asList 或者 Java8的stream流式处...【详细内容】
2021-12-27  CF07    Tags:Java   点击:(3)  评论:(0)  加入收藏
文章目录 如何理解面向对象编程? JDK 和 JRE 有什么区别? 如何理解Java中封装,继承、多态特性? 如何理解Java中的字节码对象? 你是如何理解Java中的泛型的? 说说泛型应用...【详细内容】
2021-12-24  Java架构师之路    Tags:JAVA   点击:(5)  评论:(0)  加入收藏
大家好!我是老码农,一个喜欢技术、爱分享的同学,从今天开始和大家持续分享JVM调优方面的经验。JVM调优是个大话题,涉及的知识点很庞大 Java内存模型 垃圾回收机制 各种工具使用 ...【详细内容】
2021-12-23  小码匠和老码农    Tags:JVM调优   点击:(12)  评论:(0)  加入收藏
前言JDBC访问Postgresql的jsonb类型字段当然可以使用Postgresql jdbc驱动中提供的PGobject,但是这样在需要兼容多种数据库的系统开发中显得不那么通用,需要特殊处理。本文介绍...【详细内容】
2021-12-23  dingle    Tags:JDBC   点击:(13)  评论:(0)  加入收藏
Java与Lua相互调用案例比较少,因此项目使用需要做详细的性能测试,本内容只做粗略测试。目前已完成初版Lua-Java调用框架开发,后期有时间准备把框架进行抽象,并开源出来,感兴趣的...【详细内容】
2021-12-23  JAVA小白    Tags:Java   点击:(11)  评论:(0)  加入收藏
Java从版本5开始,在 java.util.concurrent.locks包内给我们提供了除了synchronized关键字以外的几个新的锁功能的实现,ReentrantLock就是其中的一个。但是这并不意味着我们可...【详细内容】
2021-12-17  小西学JAVA    Tags:JAVA并发   点击:(11)  评论:(0)  加入收藏
一、概述final是Java关键字中最常见之一,表示“最终的,不可更改”之意,在Java中也正是这个意思。有final修饰的内容,就会变得与众不同,它们会变成终极存在,其内容成为固定的存在。...【详细内容】
2021-12-15  唯一浩哥    Tags:Java基础   点击:(17)  评论:(0)  加入收藏
1、问题描述关于java中的日志管理logback,去年写过关于logback介绍的文章,这次项目中又优化了下,记录下,希望能帮到需要的朋友。2、解决方案这次其实是碰到了一个问题,一般的情况...【详细内容】
2021-12-15  软件老王    Tags:logback   点击:(19)  评论:(0)  加入收藏
本篇文章我们以AtomicInteger为例子,主要讲解下CAS(Compare And Swap)功能是如何在AtomicInteger中使用的,以及提供CAS功能的Unsafe对象。我们先从一个例子开始吧。假设现在我们...【详细内容】
2021-12-14  小西学JAVA    Tags:JAVA   点击:(22)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条