【23】springboot integrated spring business detailed explanation and actual combat

        I have been in the extremely superficial stage of interview theory for the content of spring affairs . In fact, I have not studied and summarized it carefully. This time I spent some time studying spring affairs and summarized my study notes here. Let’s start all. First of all, I will do my own understanding and interpretation from the concept of spring transaction to the use of code.

        We will start learning step by step from the following points:

             1. What is a spring transaction.

             2. Why does the newly created springboot project sometimes come with transaction processing and sometimes without transaction processing.

             3. There are several ways to use and use spring transactions.

             4. The operation drill of multiple attributes of spring transaction .

The demo in this chapter is modified         using the previous springboot integration swagger demo , and the code will be uploaded to git.

Qq exchange group navigation ——> 231378628

 The overall column of the springboot chapter: 


[1] springboot integrates swagger (super detailed

[2] springboot integrates swagger (custom) (super detailed)

[3] springboot integration token (super detailed)

[4] springboot integrates mybatis-plus (super detailed) (on)

[5] springboot integrates mybatis-plus (super detailed) (below)

[6] springboot integrates custom global exception handling

[7] springboot integrates redis (super detailed)

[8] springboot integrates AOP to realize log operation (super detailed)

[Nine] springboot integrated timing tasks (super detailed)

[10] springboot integrates redis to realize the startup service, that is, save the hotspot data in the global and redis (super detailed)

[Eleven] springboot integrates quartz to realize timing task optimization (super detailed)

[Twelve] springboot integrates thread pool to solve high concurrency (super detailed, keep you understanding)

[Thirteen] springboot integrates asynchronous calls and obtains return values ​​(super detailed)

[14] springboot integrates WebService (super detailed)

[Fifteen] springboot integrates WebService (about passing parameters) (super detailed)

[16] springboot integrates WebSocket (super detailed)

[Seventeen] springboot integrates WebSocket to realize chat room (super detailed)

[Eighteen] springboot implements custom global exception handling

[Nineteen] springboot integrates ElasticSearch actual combat (ten thousand characters)

[Twenty] springboot integration filter combat

[21] springboot integrates interceptors in actual combat and compares filters

[22] springboot integration activiti7 (1) practical demonstration

【23】springboot integrated spring business detailed explanation and actual combat

[24] springboot uses EasyExcel and thread pool to realize multi-threaded import of Excel data

[25] springboot integrates jedis and redisson Bloom filters to handle cache penetration

[26] springboot implements multi-threaded transaction processing_springboot multi-threaded transaction

[27] springboot realizes the function of saving the current login information like the session through the threadLocal+ parameter parser


a9c53926625446808a2e15b6c7d63e87.png

Table of contents

1. What is a spring transaction

2. Why does the newly created springboot project sometimes come with transaction processing and sometimes without transaction processing

3. How to use spring transactions and how to use them

Fourth, the practical operation of multiple attributes of spring transactions

1. Whether the transaction has only read permission (read-only)

2. The transaction is rolled back after the specified exception occurs (rollback-for)

3. Do not roll back after the specified exception occurs in the transaction (no-rollback-for)

4. Transaction isolation level (isolation)

5. Transaction propagation (propagation)

6. Transaction timeout (timeout)


1. What is a spring transaction

        Spring transactions are similar to mysql transactions, and they are also the features and functions of mysql transactions.

Four characteristics of transactions:

name describe
consistency The integrity of data must remain consistent before and after transaction execution.
atomicity A transaction is an indivisible unit, and the contents inside are either executed or not executed
isolation When multiple users access the database concurrently, the transactions of multiple users do not affect each other, and the data of multiple concurrent transactions should be isolated from each other.
Persistence Modifications to the database by committed transactions should be permanently stored in the database

Transaction isolation level:

        The tables are described in the second section below, and will not be repeated here.

Transaction propagation mechanism:

        The table in the second section below is also described, so I won’t repeat it here. If you want to see it, go downstairs.

Summarize:

        Spring affairs are probably these points. The most commonly used purpose of using him is his four major features. I think the most important one is atomicity, keeping the database operations in the method either all succeed or all fail.

        /The following is a study on why sometimes I feel that the transaction processing seems to have come with the project, and sometimes I feel that there is no transaction processing./ .


2. Why does the newly created springboot project sometimes come with transaction processing and sometimes without transaction processing

        To solve this problem, you need to go to the project to find out whether such a class DataSourceTransactionManager is registered in the spring container. If it exists, you can use the transaction. If it does not exist, you need to import the dependent jar package with this class, similar to mybatis and spring-jdbc Depends on this class below.

1fee1d8d7e5d4a499315caecf4b3e01c.png

        After you find this class, it means that your project supports transaction processing, but it’s just a matter of whether it’s started or whether the transaction is invalid or not. Here are two ways to start a transaction. This article focuses on explaining the xml+aop form (to facilitate global processing).


3. How to use spring transactions and how to use them

        As mentioned above, when the DataSourceTransactionManager class exists in the project, transactions can be used. There are two ways to start transactions, as follows:

open method Concrete operation
Annotation method

1. Add the annotation @EnableTransactionManagement to the startup class to enable the transaction processing function.

2. Annotate @Transactional on the method that requires transaction processing to perform transaction processing.

xml way

1. Create a new xml file, create new bean, tx, aop tags, and configure the places that need transaction processing.

2. Import the resource through the @ImportResource annotation in the startup class @ImportResource("classpath:transaction.xml")

Use one of the         above two methods .

The following demonstrates the two methods:

1: Annotation method (this chapter does not focus on explanation)

When not opening a transaction:

d8c1c3185add44a88503fb422f985edc.png

5be1f4eb5fdf4e1f95aec461c61900bf.png

As you can see from the above code, after executing the save statement of mybatis-plus, an error will be reported, and the exception is not handled manually. In this case, will the save be successful? The answer is yes, because there is no transaction processing, the test is as follows:

Data sheet before test:

0d805942446f46039a4025192f074465.png​Call the test interface:

42391efdc7194deb910b14315a9d96a4.png

Data table after testing:

9f0fcb89f3cd4c049ffcb6b8c4f82dd7.png

result:

Although an error was reported, the data was still saved, and no transaction processing was performed automatically

When starting a transaction:

cae9fd0d27bd4957a46614a4ae0f8db1.png

0e2d7d3ef8ea43d6bc901d647135fccf.png

Transaction processing is enabled through annotations, and the following is being tested.

Data sheet before test:

612ad8ef9f8b42a29c034dc383c1e923.png

Call the test interface:

22e7af892b774de791e07ec441ae6804.png

The interface still reports an error where the denominator of the code calculation is 0.

Data sheet after test:

ccc6246be3aa488180173aef8bd78918.png

The data in the data table is not added, which means that the data is rolled back after an error is reported , which means that the transaction processing has been carried out , and the transaction processing has been successfully opened. But this method has a big trouble point. You need to add @Transactional annotations to all methods that require transaction processing . It can be realized by xml+aop. The key learning object of this chapter is to realize spring transaction processing by xml.

2: xml mode

When not opening a transaction:

Delete the two annotations added during the above test, and then test the transaction processing of the interface. The above has been tested and will not be written here.

When starting a transaction:

Opening method: *******************

Create the transaction.xml file first, as follows:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
	   xmlns:tx="http://www.springframework.org/schema/tx"
	   xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">

	<!--  定义事务管理对象	-->
	<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource" ></property>
	</bean>

	<!--  配置事务处理	-->
	<tx:advice id="txAdvice" transaction-manager="txManager">
		<tx:attributes>
			<tx:method name="*" read-only="true" timeout="7200" />
			<tx:method name="get*" rollback-for="Exception" read-only="true" ></tx:method>
			<tx:method name="add*" ></tx:method>
			<tx:method name="delete*" rollback-for="Exception" read-only="true" ></tx:method>
			<tx:method name="update*" rollback-for="Exception" read-only="true" ></tx:method>
		</tx:attributes>
	</tx:advice>

	<!--  配置aop的切点和切点的处理	-->
	<aop:config>
		<aop:pointcut id="allManagerMethod" expression="execution (* com.swagger.demo.service.UserService.*(..))" />
		<aop:advisor advice-ref="txAdvice" pointcut-ref="allManagerMethod" order="0"/>
	</aop:config>

</beans>

The code is interpreted as follows: 

b0ed23cd958047d1b530b2b661d0ae55.png​1 : Here is the definition of the transaction management object, which is the class mentioned above. The screenshot here is popular because the configuration file has not been imported into the startup class of the springboot project.

a9950e22948e4d2e8b45e961ed779c16.png

2: Define the cut point through aop, and cut to the place where the transaction needs to be processed. The matching method inside is the matching rule of the aop cut point. Baidu, there are not many things, so I won’t expand it here. 

571eab00d8f6459185e0430609b90079.png

3: Create the tx tag, associate the aop object with the transaction management object, and configure the place where transaction processing is required. The properties of the tx tag are explained below.

attribute name describe

name

The method name of transaction processing can be fuzzy matched with the method name by *, and the processing method is the position where the aop point cuts. There is no default value .

read-only

Whether the transaction has only read-only access to the database, true, false, the default is false .

rollback-for

Rollback after the specified exception occurs, separated by commas, the default value is runtimeException

isolation

Transaction isolation level.

1: default: The database automatically determines what isolation level should be used. The default is default .

2: read_uncommitted: Uncommitted data can be read. Dirty reads, unique reads, and phantom reads may occur. Highest efficiency.
3: read_committed: can only read data that has been committed by other transactions. Dirty reads can be prevented, and non-repeatable reads and phantom reads may occur.

4: repeatable_read: The read data is locked to prevent other transactions from modifying this data. It can prevent dirty reads, non-repeatable reads, and possible phantom reads.
5: serializable: Queue operation, lock the entire table. When a transaction is operating data, another transaction must wait for the transaction operation to complete before operating the table.

no-rollback-for

When the specified exception occurs, it will not be rolled back. Multiples are separated by commas, and there is no default value .

propagation

Transaction propagation.

1: REQUIRED: Support the current transaction, if there is no current transaction, create a new transaction. This is the most common choice. (default REQUIRED)

2: SUPPORTS: Support the current transaction, if there is no current transaction, it will be executed in a non-transactional manner.

3: MANDATORY: Support current transaction, if there is no current transaction, an exception will be thrown.

4: REQUIRES_NEW: create a new transaction, if there is a current transaction, suspend the current transaction.

5: NOT_SUPPORTED: Execute the operation in a non-transactional manner. If there is a current transaction, suspend the current transaction.

6: NEVER: Execute in a non-transactional manner, if there is a current transaction, an exception is thrown.

7:NESTED:支持当前事务,如果当前事务存在,则执行一个嵌套事务,如果当前没有事务,就新建一个事务。

timeout

事务超时,就是指一个事务所允许执行的最长时间,如果超过该时间限制但事务还没有完成,则自动回滚事务,没有默认的超时时间。

ps:创建好xml文件后,其次记得要引入aop的jar包,不然启动报错,因为xml文件使用了aop的标签。

c8ea062567f74d5692e2cc27d41e7fbe.png

最后,启动类导入该文件,@ImportResource("classpath:transaction.xml")

这个东西注意了,必须加上,否则事务配置的xml文件不会生效,一定记得加哦!!!

2d376460f9834c7884074c6321e5f4ac.png

创建好xml文件并导入后,我们继续测试add方法,并采用所有的默认spring事务配置进行测试(后面小节进行其他属性的一一测试)。  

32d142a936bd43bba74aa7f4b53ad877.png

测试前数据表:

4685e2c6c66c4cbeb5ae57dd76fae7e6.png

调用接口:

d2560bff7a2642608beea027f797987f.png

测试后数据表:

a592ac64c4bf4532b1513035b93d270e.png

数据表没有新增数据,说明采用标签的默认的事务处理是生效了的。后面小节针对上面表格的6个属性值(read-only,rollback-for,isolation,no-rollback-for,propagation,timeout)进行学习。


四、spring事务的多个属性的实际操作演练

1、事务是否只有可读权限(read-only)

        针对这个属性的学习还是拿上面的add方法进行测试。

false时:

cecde198a43e469db161aee85f58f0b9.png

c85ee17b9cf44d52bf909ca53d449779.png

默认是false,所以当不写时就是false,测试上面add方法是否会新增成功呢?答案是:肯定会

2f63754045d14be5a05f7dfca2bd2241.png

7c1c87308361425d9a2206669f6d490b.png

true时:

82dc7ae5590c4390816a7d47437ae9db.png

6406353d73384eabb69e8c969bba4860.png

        上面这种情况时呢,会发生什么?

46d507489eb545118c4e381987016b29.png

17234fa455714fac9d22664bfb86425c.png

46a9e28e2143494896e6120801e270ec.png

        可以发现接口报了sql异常了,连接只可以读,数据库数据也没有新增,确实进行了事务处理

        接下来再试试另一个参数rollback-for的学习,指定异常回滚


2、事务发生指定的异常后回滚(rollback-for

        由于Spring事务的回滚会自动回滚发生的runtimeException异常,所以本小结的学习自定义一个自己的异常类型——MyException

6520f0d5b8314c94a6556d4dc37f9a37.png

        然后改造add方法。如下:

3615ea56295247e39b6648a140a93438.png

        手动捕获这个runtimeException异常,然后由我们自己手动抛一个自定义的异常出去,再不修改 rollback-for属性的情况下,调用接口,事务会回滚吗?答案是不会,因为我自定义的异常继承自Exception,而不是运行时异常,测试看看,调用接口前数据库表是这样的:

c3b121704d784130be616f017549289b.png

调用接口后:

213f457ede454e628be762393075eef3.png

b77785938e2245c895ec40a7fce614e1.png

9eafa2d9e83746e398c80b62ac77c43a.png

        虽然报错了,但是数据库数据仍然新增成功了,并没有回滚,没有事务处理

        下面试试rollback-for属性的作用。

ed3a52d8f50e418584d24985bc520b89.png

        再进行测试。

测试前数据表:

efe93a32d78440bcbddc59b45b60f236.png

调用接口后:

c4c86a55e145416bb9404ab39a631322.png​ b27ef227696345878e7bf5b69cb3c089.png

        数据显然没有新增成功,所以事务回滚了,进行了事务处理,rollback-for的作用体现出来了,若需要让事务处理多个自定义异常的话,用逗号隔开即可,如:<tx:method name="add*" rollback-for="MyException,MyException2,MyException3" ></tx:method>。

补充:关于异常回滚这块,需要注意一个东西:try-catch手动捕获异常,即使是runtimeException类型的异常,若手动捕获了异常并没有再抛出runtimeException异常(要把异常抛出去,抛到方法外让别人能发现,不能自己抓起来),就不会进行事务处理了就是所谓的事务失效

        意思就是如下情况:

58b977b9b2cc461eab32dbb6537d7003.png

手动捕获,但是抛出了运行时异常,能回滚

c60e508ea38549efa6393644941ca56f.png

手动捕获,但是未做其他处理,不能回滚

c2b62eb0d25445638942275391cecfe9.png

直接抛出运行时异常类ArithmeticException,继承至运行时异常类,能回滚

        言归正传,下面学习no-rollback-for属性,设置指定异常不回滚


3、事务发生指定的异常后不回滚(no-rollback-for

        上面有说到运行时异常都会进行事务处理,demo中的ArithmeticException异常就是runtimeException,若现在我需要设置即使发生这个异常也不回滚,怎么做呢?下面就可以通过这个属性实现。

27ce5b0e9c7640a9b34976d8f5730d58.png

        上面已经测试过发生这个异常会回滚,所有这里直接测试将这个属性设置到no-rollback-for属性,测试是不是不会回滚?

fa28804eb26442e88189170e6be35ad8.png

30f74b1fc11144b5b8ae8f867df3cf0e.png

测试前数据库表:

81c7cda2d6b2452b83146d20250f55fb.png调用接口:

804e0b0823ed4349a33faaf10154da00.png

c660e833db284d7bac8b46aa8ea18503.png

00edcacf0ee6455ab6a4ecf38f07dde6.png

        虽然报错了,但是仍然插入了数据,说明的确在设置no-rollback-for属性值为ArithmeticException时,Spring事务不回滚了,前面的提出的假设需求就回答了,这就是no-rollback-for属性的作用。同样的,若需要处理多个异常不进行事务处理,就用逗号隔开即可。


4、事务隔离级别(isolation

        事务隔离级别一直都是懵懵懂懂的概念,这次浅学一下。

        isolation属性就是设置事务隔离级别的,默认是default(由数据库自动判断应使用什么隔离级别)。

        这一小节就测试一下read_uncommitted(可以读取未提交的数据。可能出现脏读、不重复读、幻读。效率最高)。

        首先先查看下自己的mysql是使用的什么隔离级别

mysql版本 查看隔离级别方式
8.0以上

select @@transaction_isolation 

8.0以下

select @@tx_isolation

f332772ff4d1421e95d437dc2d29029a.png

        这是我的(可重复度,即mysql默认的隔离级别) 。

        下面开始通过两个接口来测试事务隔离级别读未提交(read_uncommitted)。

        现在模拟一种情况张三在新增一个用户"马冬梅",但是事务还没有执行完,还没有提交到数据库,这个时候李四上去查询用户,如果是default情况下,李四是肯定查询不到"马冬梅"的,为default时,我已经测试过了,查询不到,但是我现在抽风了,我就是要查询到这个"马冬梅",怎么办?就可以设置事务隔离级别为读未提交,下面开始整这个demo。

        1、还原add方法,并新增一个get方法用于查询所有用户。 

e8891576a4774170aa7d513c71be6e12.png

       2、改造xml文件,设置这两个方法的事务隔离级别。

33ec047640d144f9b591831c8b28df5d.png

        3、运行这个项目,跑两个端口,一个给张三用于新增,一个给李四用于查询。

0586d1f9d9a6426d95cbc32d7af1eb7d.png

        先看看现在表的情况。

427d3eec11404742a34c8b2fee2fe3bb.png

        有这样5条数据。

        张三现在用8085端口新增马冬梅(在add方法加个断点,防止数据立刻提交),李四用8086查询

b2b4b73933ff4810894be41dfac28e3b.png

        张三新增马冬梅,断点不放开。

9719404ef1b64d348c798ac80ad8ee81.png

13da00933f7a4b16b84d555ed9250939.png​        可以看到数据库表数据未新增,因为事务还没有提交嘛。现在让李四到8086端口查询。

0a403460794f46329336c8867752cfd6.png

        可以看到,李四查询出了张三还未提交事务到数据库的数据"马冬梅"。

        后面的其他隔离级别这里就不写了,太多了。 


5、事务传播性(propagation

        除了事务隔离级别,还有个事务传播机制也经常被面试官问到,趁现在也大概学习一下。

        本小结通过设置REQUIRED(支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择,也是最简单的处理)进行学习。默认的传播机制是也是REQUIRED。通过学习,我认为事务传播性基本上就是发生在多个方法上,比如A方法有事务,A方法内调用B方法,而B方法也有事务,或者A方法没有事务时,事务它到底如何处理,这就是事务传播机制。

        我先用语言描述一下我对于默认的REQUIRED的了解。

        假设如果有一个A方法需要新增用户的基本信息,而B方法需要新增他的父亲和母亲的基本信息,则在A方法新增完自己的信息后调用B方法。若两个方法都存在事务时,则B方法的事务就不会创建,而是和A方法公用一个事务,意思就是出异常了就一起回滚;而若方法不存在事务,B方法存在事务,就会新建一个B方法自己的事务,A方法出异常也不会回滚,而B方法会回滚。

        下面通过代码实现。

        新建一个service和实现类存放新增父母信息的方法(原因:放在同一个类下会发生事务失效的问题,我试了很久,你也可以试一下,要放在不同类下),如下:

1659ac9725de471081614acd0101cccf.png

1、新增addFather方法

8b5fb800e0214a558c96c551988d72e0.png​2、改造原来的add方法

34c9080fdc9b4452a0e59eeb00a09635.png​3、新增addFather方法的事务处理

f8aa1cc674d044d8b46d31704f4baf8f.png

测试前数据表数据:

8989cd2ac57d4d829c6626c5a84b62a7.png调用接口测试:

10eab4eaa3d349e1bb7d3845839340ba.png

4d572e6183cb42fcbaa085dcacebbc95.png

02f162069ef74a29bbbb268781e2dce3.png​        发现数据库没有新增数据,两个方法的事务都回滚了,说明第二个事务在发现当前存在事务时,直接加入了第一个事务,只存在同一个事务。

        The next test is that if only B has a transaction and A does not have a transaction, will B create a new transaction, and the effect prediction will be that Ma Dongmei will add a new transaction successfully, but his parents will not add a new transaction successfully.

The test operation is as follows:

1. Close the transaction of the add method, and only open the transaction of the addFather method

0c0a11c593b44a7a83a0eebd682fe099.png

Data sheet before test:

8989cd2ac57d4d829c6626c5a84b62a7.png

Call interface:

1b2d1afd5be047619c4d2abb852b86b7.png

0eb17dfebf464ec3bac50d33b6bfd326.png

9b40082c42094c53bb7620b35f4900fc.png

        Result: A runtime exception occurred , and the transaction of method B was rolled back , but the transaction of method A was not rolled back , indicating that method B created a new transaction of its own when no transaction currently exists.


6. Transaction timeout ( timeout )

        For the study of transaction timeout, continue to learn through the demo of the add method.

Note: The timeout here is the timeout of the database connection, not the timeout of the entire method. If you are interested, you can try thread sleep in the method. You can see that the transaction will not be rolled back. I have tried it, haha.

        Modify the add method, because each insertion method is too short, directly give him a loop 10,000 times.

before testing:

aded01e6a71248be825c5e855b06842d.png

4b420dd4192d4fb6aa09a1693eb074e9.png

95bb80b057874b049abfcc5ce77c4725.png

After calling the interface:

66be7aa4c5f1411f80a17d311f6a0ab2.png

587139b6c4374206a2a8204e19be62a1.png

a279c30a2ec048d28404a134fd830ac9.png

A timeout transaction is         successfully triggered . When I was studying, I couldn’t test the effect of this timeout period, and I always felt that it was useless. I just gave him a 1 millisecond timeout, and then rolled back for me, and finally it worked. Remember: only the time-consuming jdbc operation after the database connection is counted as the timeout period, and the business code timeout period in the method is not counted (remember this small pit).

Guess you like

Origin blog.csdn.net/weixin_56995925/article/details/125577851