一、spring的事务机制
所有的数据访问技术都有事务处理机制,这些技术提供了api用来开启事务、提交事务来完成数据操作,或者在发生错误的时候回滚数据。
而spring的事务机制是用统一的机制来处理不同数据访问技术的事务处理。spring的事务机制提供了一个platformtransactionmanager接口,不同的数据访问技术的事务使用不同的接口实现:
在程序中定义事务管理器的代码如下:
1
2
3
4
5
6
|
@bean public platformtransactionmanager transactionmanager() { jpatransactionmanager transactionmanager = new jpatransactionmanager(); transactionmanager.setdatasource(datasource()); return transactionmanager; } |
二、声明式事务
spring支持声明式事务,即使用注解来选择需要使用事务的方法,它使用@transactional注解在方法上表明该方法需要事务支持。
1
2
3
4
|
@transactional public void savesomething( long id, string name) { //数据库操作 } |
在此处需要特别注意的是,此@transactional注解来自org.springframework.transaction.annotation包,而不是javax.transaction。
spring提供了一个@enabletransactionmanagement注解在配置类上来开启声明式事务的支持。使用了@enabletransactionmanagement后,spring容器会自动扫描注解@transactional的方法和类。@enabletransactionmanagement的使用方式如下:
1
2
3
4
5
|
@configuration @enabletransactionmanagement public class appconfig { } |
三、类级别使用@transactional
@transactional不仅可以注解在方法上,也可以注解在类上。当注解在类上的时候意味着此类的所有public方法都是开启事务的。如果类级别和方法级别同时使用了@transactional注解,则使用在类级别的注解会重载方法级别的注解。
四、spring data jpa的事务支持
spring data jpa对所有的默认方法都开启了事务支持,且查询类事务默认启用readonly=true属性。
这个从源码simplejparepository中可以看出,simplejparepository在类级别定义了@transactional(readonly=true),而在和save、delete相关的操作重写了@transactional属性,此时readonly属性是false,其余查询操作readonly仍然为false。
五、spring boot的事务支持
1.自动配置的事务管理器
在使用jdbc作为数据访问技术的时候,springboot为我们定义了platformtransactionmanager的实现datasourcetransactionmanager的bean;配置见org.springframework.boot.autoconfigure.jdbc.datasourcetransactionmanagerautoconfiguration类中的定义:
1
2
3
4
5
6
|
@bean @conditionalonmissingbean @conditionalonbean (datasource. class ) public platformtransactionmanager transactionmanager() { return new datasourcetransactionmanager( this .datasource); } |
在使用jpa作为数据访问技术的时候,spring boot为我们了定义一个platformtransactionmanager的实现jpatransactionmanager的bean;配置见org.springframework.boot.autoconfigure.orm.jpa.jpabaseconfiguration.class类中的定义:
1
2
3
4
5
|
@bean @conditionalonmissingbean (platformtransactionmanager. class ) public platformtransactionmanager transactionmanager() { return new jpatransactionmanager(); } |
2.自动开启注解事务的支持
spring boot专门用于配置事务的类为:org.springframework.boot.autoconfigure.transaction.transactionautoconfiguration,此配置类依赖于jpabaseconfiguration和datasourcetransactionmanagerautoconfiguration。
而在datasourcetransactionmanagerautoconfiguration配置里还开启了对声明式事务的支持,代码如下:
1
2
3
4
5
6
|
@conditionalonmissingbean (abstracttransactionmanagementconfiguration. class ) @configuration @enabletransactionmanagement protected static class transactionmanagementconfiguration { } |
所以在spring boot中,无须显示开启使用@enabletransactionmanagement注解。
六、实例(springboot)
1.pom.xml:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
<dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-web</artifactid> </dependency> <dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-data-jpa</artifactid> </dependency> <dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-data-rest</artifactid> </dependency> <dependency> <groupid>mysql</groupid> <artifactid>mysql-connector-java</artifactid> <scope>runtime</scope> </dependency> |
2.application.yml:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
server: port: 5000 spring: datasource: driver- class -name: com.mysql.jdbc.driver url: jdbc:mysql: //localhost:3306/test?useunicode=true&characterencoding=utf8&charactersetresults=utf8 username: root password: password jpa: hibernate: ddl-auto: update # 第一次简表create 后面用update show-sql: true |
3.实体类staff:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
@entity public class staff { @id @generatedvalue private long id; private string name; private integer age; private string address; public staff() { super (); } public staff( long id, string name, integer age, string address) { super (); this .id = id; this .name = name; this .age = age; this .address = address; } //省略get、set方法 } |
4.staff的repository:
1
2
3
|
public interface staffrepository extends jparepository<staff, long > { } |
5.服务接口:
1
2
3
4
|
public interface staffservice { public staff savestaffwithrollback(staff staff); //回滚 public staff savestaffwithoutrollback(staff staff); //不回滚 } |
6.服务实现:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
@service public class staffserviceimpl implements staffservice { @autowired staffrepository staffrepository; //可以直接注入我们的rersonrepository的bean。 @override //使用@transactional注解的rollbackfor属性,指定特定异常时,数据回滚。 @transactional (rollbackfor = {illegalargumentexception. class }) public staff savestaffwithrollback(staff staff) { staff s = staffrepository.save(staff); if (staff.getname().equals( "张三" )) { throw new illegalargumentexception( "张三已经存在了,rollback" ); } return s; } @override public staff savestaffwithoutrollback(staff staff) { staff s = staffrepository.save(staff); if (staff.getname().equals( "张三" )) { throw new illegalargumentexception( "张三已经存在了,数据不回滚" ); } return s; } } |
7.controller:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
@restcontroller @requestmapping ( "/staff" ) public class staffcontroller { @autowired staffservice staffservice; //测试回滚情况 @requestmapping ( "/rollback" ) public staff rollback(staff staff) { return staffservice.savestaffwithrollback(staff); } //测试不回滚情况 @requestmapping ( "/notrollback" ) public staff norollback(staff staff) { return staffservice.savestaffwithoutrollback(staff); } } |
8.运行测试:
(1)回滚:http://localhost:5000/staff/rollback?name=张三&age=18
控制台:
数据库:
(2)不回滚:http://localhost:5000/staff/notrollback?name=张三&age=18
控制台:
数据库:
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。