What is a transaction
1. What is a transaction
Transaction refers to a set of sql statements, in which there are multiple sql statements
It may be insert, update, select or delete. We hope that these multiple sql statements can succeed or fail. The execution of these sql statements is consistent and executed as a whole.
2. When do you think of using transactions
When my operation involves getting multiple tables or insert ing, updating and deleting multiple sql statements. You need to ensure that these statements are successful to complete my function, or fail to ensure that the operation meets the requirements.
3. What kind of transaction is required by your business method, and describe the type of transaction required.
Describe the transactions required by the method:
Isolation level of transaction:
There are four values. (packaging safety in case of high concurrency)
These constants are based on ISOLATION_ start. Isometric ISOLATION_XXX.
- DEFAULT: the DEFAULT transaction isolation level of DB is adopted. MySql defaults to REPEATABLE_READ; Oracle defaults to READ_COMMITTED.
- READ_UNCOMMITTED: read uncommitted. No concurrency issues were resolved.
- READ_COMMITTED: read committed. Solve dirty reading, there are non repeatable reading and unreal reading.
- REPEATABLE_READ: repeatable. Solve dirty reading, non repeatable reading and phantom reading
- SERIALIZABLE: serialization. There is no concurrency problem.
Timeout of transaction
Indicates the longest execution time of a method. If the execution time of the method exceeds the time, the transaction will be rolled back.
The unit is seconds, integer value, and the default is - 1
Propagation behavior of transactions
Control whether business methods have transactions and what kind of transactions they have.
7 propagation behaviors, indicating that when your business method is called, the transaction is used between methods.
-
PROPAGATION_REQUIRED
The specified method must be executed within a transaction. If there is a current transaction, it will be added to the current transaction; If nothing happens at present
Create a new transaction. This propagation behavior is the most common choice and the default transaction propagation behavior of Spring.
If the propagation behavior is added to the doOther() method. If the doSome() method is calling the doOther() method, it is doing something
If it runs in the transaction, the execution of the doOther() method is also added to the transaction for execution. If the doSome() method is called
If the doOther() method is not executed within a transaction, the doOther() method creates a transaction and executes it.
-
PROPAGATION_REQUIRES_NEW
The specified method supports the current transaction, but if there is no current transaction, it can also be executed in a non transactional manner.
-
PROPAGATION_SUPPORTS
Always create a new transaction. If there is a current transaction, suspend the current transaction until the new transaction is executed.
The above three need to be mastered
- PROPAGATION_MANDATORY
- PROPAGATION_NESTED
- PROPAGATION_NEVER
- PROPAGATION_NOT_SUPPORTED
4. The time when the transaction is committed and rolled back
- When your business method is executed successfully, no exception is thrown. When the method is executed, spring commits the transaction after the method is executed. Transaction manager commit
- When your business method throws a runtime exception or ERROR, spring executes rollback and calls the rollback of the transaction manager
Definition of runtime exception: RuntimeException and its subclasses are runtime exceptions, such as nullpointexception and numberformatexception - When your business method throws a non runtime exception, mainly the checked exception, commit the transaction
Checked exception: an exception that must be handled in your code. For example, IOException, SQLException
Using transaction processing steps in Spring
give an example:
Buy goods trans_sale project
This example is to purchase goods, simulate users to place orders, add sales records to the order table, and reduce inventory from the commodity table.
Implementation steps:
Step0: create database table
Create two database tables, sale and goods
1. Sales table
create table sale(id int(11) not null AUTO_INCREMENT, gid int(11) not null, nums int(11), primary key (id));
2. goods list
create table goods(id int(11) not null, name varchar(100), amount int(11), price float(0), primary key(id));
goods table data
Step 1: Maven relies on POM xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.changsha</groupId> <artifactId>springtrans</artifactId> <version>1.0-SNAPSHOT</version> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties> <dependencies> <!--Unit test dependency--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <!--aspectj rely on--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>5.2.5.RELEASE</version> </dependency> <!--Spring rely on--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.2.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>5.2.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.2.5.RELEASE</version> </dependency> <!--mybatis rely on--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.1</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>1.3.1</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.24</version> </dependency> <!--Connection pool dependency--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.12</version> </dependency> </dependencies> <build> <resources> <resource> <directory>src/main/java</directory><!--Directory of--> <includes><!--Including the.properties,.xml The files will be scanned--> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>false</filtering> </resource> </resources> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.1</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> </project>
Step 2: create entity class
Used to store the data of a row in the database table
The goods class holds a row of data in the goods table
package com.changsha.domain; public class Goods { private Integer id; private String name; private Integer amount; private Float price; public Goods() { } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAmount() { return amount; } public void setAmount(Integer amount) { this.amount = amount; } public Float getPrice() { return price; } public void setPrice(Float price) { this.price = price; } @Override public String toString() { return "Goods{" + "id=" + id + ", name='" + name + '\'' + ", amount=" + amount + ", price=" + price + '}'; } }
One row of data in sale table
package com.changsha.domain; public class Sale { private Integer id; private Integer gid; private Integer nums; public Sale(Integer id, Integer gid, Integer nums) { this.id = id; this.gid = gid; this.nums = nums; } public Sale() { } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Integer getGid() { return gid; } public void setGid(Integer gid) { this.gid = gid; } public Integer getNums() { return nums; } public void setNums(Integer nums) { this.nums = nums; } @Override public String toString() { return "Sale{" + "id=" + id + ", gid=" + gid + ", nums=" + nums + '}'; } }
Step 3: define dao interface
Define the interfaces of two Daos, sale dao and goodsdao
dao interface, which defines the operation on the database
package com.changsha.dao; import com.changsha.domain.Goods; import org.apache.ibatis.annotations.Param; public interface GoodsDao { //Update inventory //Goods refers to the information of the goods purchased by the user this time int updateGoods(Goods goods); //Query commodity information Goods selectGoods(@Param("gid") Integer id); }
dao of sale
package com.changsha.dao; import com.changsha.domain.Sale; public interface SaleDao { //Add sales record int insertSale(Sale sale); }
Step 4: define the sql mapping file corresponding to dao interface
mapper configuration file (need to have the same name and directory as dao interface)
GoodsDao.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!-- namespace: Must have a value, a unique custom string Recommended: dao Fully qualified name of the interface Declarative id The suggestion is the same as the name of the interface method --> <mapper namespace="com.changsha.dao.GoodsDao"> <update id="updateGoods"> update goods set amount = amount - #{amount} where id = #{id} </update> <select id="selectGoods" resultType="com.changsha.domain.Goods"> select * from goods where id = #{gid} </select> </mapper>
SaleDao.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!-- namespace: Must have a value, a unique custom string Recommended: dao Fully qualified name of the interface Declarative id The suggestion is the same as the name of the interface method --> <mapper namespace="com.changsha.dao.SaleDao"> <insert id="insertSale"> insert into sale(gid,nums) values (#{gid},#{nums}) </insert> </mapper>
Define exception class (not required)
Define the exception class NotEnoughException that may be thrown by the service layer
package com.changsha.excep; //Custom runtime exception public class NotEnoughException extends RuntimeException{ public NotEnoughException() { super(); } public NotEnoughException(String message) { super(message); } }
Step 5: create mybatis master configuration file
Because other connection pools are used, the database information does not need to be specified in this file
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <!--settings: control mybatis Global behavior--> <settings> <!--set up mybatis Output log--> <setting name="logImpl" value="STDOUT_LOGGING"/> </settings> <!--Alias settings--> <typeAliases> <!--name:Package name of entity class express com.bjpowernode.domain The column names in the package are aliases You can use Student express com.bjpowenrode.domain.Student --> <package name="com.changsha.domain"/> </typeAliases> <!-- sql mapper(sql Mapping file)Location of--> <mappers> <!-- name: Is the name of the package. All the files in this package mapper.xml It can be loaded at one time --> <package name="com.changsha.dao"/> </mappers> </configuration>
Step 6: define Service interface
Define the Service interface BuyGoodsService
package com.changsha.service; public interface BuyGoodsService { //The method of purchasing goods. goodsId is the number of the purchased goods, and num is the quantity of the goods public void buy(Integer goodsId, Integer nums); }
Step 7: define the implementation class of the service
Defines the implementation class BuyGoodsServiceImpl of the service layer interface
package com.changsha.service.Impl; import com.changsha.dao.GoodsDao; import com.changsha.dao.SaleDao; import com.changsha.domain.Goods; import com.changsha.domain.Sale; import com.changsha.excep.NotEnoughException; import com.changsha.service.BuyGoodsService; public class BuyGoodsServiceImpl implements BuyGoodsService { private SaleDao saleDao; private GoodsDao goodsDao; @Override public void buy(Integer goodsId, Integer nums) { System.out.println("=======buy Start of method======="); //Record sales information and add records to the sale table Sale sale = new Sale(); sale.setGid(goodsId); sale.setNums(nums); saleDao.insertSale(sale); //Update inventory Goods goods = goodsDao.selectGoods(goodsId); if(goods == null){ //Item does not exist throw new NullPointerException("The number is" + goodsId+"Item does not exist"); } else if(goods.getAmount() < nums){ //Insufficient inventory of goods throw new NotEnoughException("The number is" + goodsId+"Insufficient inventory of goods"); } //If there are no exceptions above, you can modify the inventory Goods buyGoods = new Goods(); buyGoods.setId(goodsId); buyGoods.setAmount(nums); goodsDao.updateGoods(buyGoods); System.out.println("=======buy Method completion======="); } public void setSaleDao(SaleDao saleDao) { this.saleDao = saleDao; } public void setGoodsDao(GoodsDao goodsDao) { this.goodsDao = goodsDao; } }
Step 8: create Spring configuration file content
1. Steps for using @ Transactional (applicable to small and medium-sized projects):
1). The transaction manager object needs to be declared
<!--Claim transaction manager--> <bean id="tansactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="myDataSource"/> </bean>
2). Turn on the transaction annotation driver and tell the spring framework that I want to use annotation to manage transactions.
spring uses the aop mechanism to create the proxy object of the class where @ Transactional is located, and adds the transaction function to the method.
spring adds transactions to business methods:
Before the execution of your business method, start the transaction first, commit or roll back the transaction after the business method, and use aop surround notification
@Around("The business method name of the transaction function you want to add") Object myAround(){ Start the transaction, spring Open it for you try{ buy(1001,10); spring Transaction manager for.commit(); }catch(Exception e){ spring Transaction manager for.rollback(); } }
Turn on spring settings for transactions
The annotation driven package must end with tx
<!--2. Turn on the transaction annotation driver and tell spring Use annotations to manage transactions and create proxy objects transaction-manager:Of the transaction manager object id--> <tx:annotation-dridven transaction-manager="tansactionManager"/>
3). Add the @ transactional annotation to the method you need to do the transaction
The code is as follows
package com.changsha.service.Impl; import com.changsha.dao.GoodsDao; import com.changsha.dao.SaleDao; import com.changsha.domain.Goods; import com.changsha.domain.Sale; import com.changsha.excep.NotEnoughException; import com.changsha.service.BuyGoodsService; import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; public class BuyGoodsServiceImpl implements BuyGoodsService { private SaleDao saleDao; private GoodsDao goodsDao; @Transactional( propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, readOnly = false, rollbackFor = { NullPointerException.class, NotEnoughException.class } ) @Override public void buy(Integer goodsId, Integer nums) { System.out.println("=======buy Start of method======="); //Record sales information and add records to the sale table Sale sale = new Sale(); sale.setGid(goodsId); sale.setNums(nums); saleDao.insertSale(sale); //Update inventory Goods goods = goodsDao.selectGoods(goodsId); if(goods == null){ //Item does not exist throw new NullPointerException("The number is" + goodsId+"Item does not exist"); } else if(goods.getAmount() < nums){ //Insufficient inventory of goods throw new NotEnoughException("The number is" + goodsId+"Insufficient inventory of goods"); } //If there are no exceptions above, you can modify the inventory Goods buyGoods = new Goods(); buyGoods.setId(goodsId); buyGoods.setAmount(nums); goodsDao.updateGoods(buyGoods); System.out.println("=======buy Method completion======="); } public void setSaleDao(SaleDao saleDao) { this.saleDao = saleDao; } public void setGoodsDao(GoodsDao goodsDao) { this.goodsDao = goodsDao; } }
Since annotations are the default values used in most cases, the assignment can be omitted directly
package com.changsha.service.Impl; import com.changsha.dao.GoodsDao; import com.changsha.dao.SaleDao; import com.changsha.domain.Goods; import com.changsha.domain.Sale; import com.changsha.excep.NotEnoughException; import com.changsha.service.BuyGoodsService; import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; public class BuyGoodsServiceImpl implements BuyGoodsService { private SaleDao saleDao; private GoodsDao goodsDao; @Transactional @Override public void buy(Integer goodsId, Integer nums) { System.out.println("=======buy Start of method======="); //Record sales information and add records to the sale table Sale sale = new Sale(); sale.setGid(goodsId); sale.setNums(nums); saleDao.insertSale(sale); //Update inventory Goods goods = goodsDao.selectGoods(goodsId); if(goods == null){ //Item does not exist throw new NullPointerException("The number is" + goodsId+"Item does not exist"); } else if(goods.getAmount() < nums){ //Insufficient inventory of goods throw new NotEnoughException("The number is" + goodsId+"Insufficient inventory of goods"); } //If there are no exceptions above, you can modify the inventory Goods buyGoods = new Goods(); buyGoods.setId(goodsId); buyGoods.setAmount(nums); goodsDao.updateGoods(buyGoods); System.out.println("=======buy Method completion======="); } public void setSaleDao(SaleDao saleDao) { this.saleDao = saleDao; } public void setGoodsDao(GoodsDao goodsDao) { this.goodsDao = goodsDao; } }
Annotate the full spring configuration file for how transactions are handled
<?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:context="http://www.springframework.org/schema/context" 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/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <!-- Write the configuration information of the database in an independent file, compile and modify the configuration content of the database spring know jdbc.properties File location --> <context:property-placeholder location="classpath:jdbc.properties" /> <!--Declare data source DataSource,The function is to connect to the database--> <bean id="myDataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> <!--set Inject into DruidDataSource Provide database information--> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> <property name="maxActive" value="${jdbc.maxActive}"/> </bean> <!--The statement is mybatis Provided in SqlSessionFactoryBean Class, which is created internally SqlSessionFactory of SqlSessionFactory sqlSessionFactory = new .. --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <!--set Injection, paying the database connection pool dataSource attribute--> <property name="dataSource" ref="myDataSource"/> <!--mybatis Location of the master profile configLocation Attribute is Resource Type, read configuration file Its assignment, using value,Specify the path of the file, using classpath:Indicates the location of the file --> <property name="configLocation" value="springtrans.xml"/> </bean> <!--establish dao Objects, using SqlSession of getMapper(StudentDao.class) MapperScannerConfigurer:Call internally getMapper()Generate each dao Proxy object for the interface.--> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <!--appoint SqlSessionFactory Object id--> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/> <!--Specify the package name, which is dao The package name of the interface. MapperScannerConfigurer It will scan all interfaces in the package and execute each interface once getMapper()Method to get the of each interface dao Object. Created dao Object into spring In the container. dao The default name of an object is the initial lowercase of the interface name --> <property name="basePackage" value="com.changsha.dao"/> </bean> <!--statement service--> <bean id="buyService" class="com.changsha.service.Impl.BuyGoodsServiceImpl"> <property name="goodsDao" ref="goodsDao"/> <property name="saleDao" ref="saleDao"/> </bean> <!--Claim transaction manager--> <bean id="tansactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="myDataSource"/> </bean> <!--2. Turn on the transaction annotation driver and tell spring Use annotations to manage transactions and create proxy objects transaction-manager:Of the transaction manager object id--> <tx:annotation-driven transaction-manager="tansactionManager"/> </beans>
2. Use aspectj framework (for large projects)
1) maven relies on POM xml
Dependency coordinates of newly added aspectj
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>5.2.5.RELEASE</version> </dependency>
2) Add a transaction manager to the container
<!--Claim transaction manager--> <bean id="tansactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="myDataSource"/> </bean>
3) Configure transaction notifications
Set relevant properties for transaction notification. Used to specify how transactions are woven into which methods.
For example, the transaction requirements applied to the buy method are necessary, and the business should be rolled back when an exception occurs in the buy method.
<!--2.Declare the transaction attributes of the business method (isolation level, propagation behavior, timeout) id:Custom name, indicating <tx:advice> and </tx:advice>Configuration content between transaction-manager:Of the transaction manager object id --> <tx:advice id="myAdvice" transaction-manager="transactionManager"> <!--tx:attributes: Configure transaction properties--> <tx:attributes> <!--tx:method: Configure transaction attributes for specific methods, method There can be multiple methods, and the transaction attributes can be set for different methods name:Method name, 1) complete method name without package and class. 2)Method can use wildcards,* Represents any character propagation: Propagation behavior, enumeration value isolation: Isolation level rollback-for: The exception class name you specified, fully qualified class name. If an exception occurs, it must be rolled back --> <tx:method name="buy" propagation="REQUIRED" isolation="DEFAULT" rollback-for="java.lang.NullPointerException,com.bjpowernode.excep.NotEnoughException"/> <!--Use wildcards to specify many methods--> <tx:method name="add*" propagation="REQUIRES_NEW" /> <!--Specify modification method--> <tx:method name="modify*" /> <!--Delete method--> <tx:method name="remove*" /> <!--Query method, query,search,find--> <tx:method name="*" propagation="SUPPORTS" read-only="true" /> </tx:attributes> </tx:advice>
In the method tag, first find the transaction method with precise range (specify method name), then find the semi universal method, and finally*
4) Configuration enhancer
Specify to whom the configured transaction notification will be woven.
<!--to configure aop--> <aop:config> <!--Configure pointcut expression: specify which classes in the package and which transactions to use id:The name and unique value of the pointcut expression expression: Pointcut expressions that specify which classes use transactions, aspectj The proxy object is created com.bjpowernode.service com.crm.service com.service --> <aop:pointcut id="servicePt" expression="execution(* *..service..*.*(..))"/> <!--Configuring enhancers: associations adivce and pointcut advice-ref:Notice, above tx:advice Where is the configuration pointcut-ref: Of pointcut expressions id --> <aop:advisor advice-ref="myAdvice" pointcut-ref="servicePt" /> </aop:config>
Pointcut expression in aspectj framework It is introduced in
Complete spring configuration file for transaction processing through aspectj framework
<?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:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- Write the configuration information of the database in an independent file, compile and modify the configuration content of the database spring know jdbc.properties File location --> <context:property-placeholder location="classpath:jdbc.properties" /> <!--Declare data source DataSource,The function is to connect to the database--> <bean id="myDataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> <!--set Inject into DruidDataSource Provide database information--> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> <property name="maxActive" value="${jdbc.maxActive}"/> </bean> <!--The statement is mybatis Provided in SqlSessionFactoryBean Class, which is created internally SqlSessionFactory of SqlSessionFactory sqlSessionFactory = new .. --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <!--set Injection, paying the database connection pool dataSource attribute--> <property name="dataSource" ref="myDataSource"/> <!--mybatis Location of the master profile configLocation Attribute is Resource Type, read configuration file Its assignment, using value,Specify the path of the file, using classpath:Indicates the location of the file --> <property name="configLocation" value="springtrans.xml"/> </bean> <!--establish dao Objects, using SqlSession of getMapper(StudentDao.class) MapperScannerConfigurer:Call internally getMapper()Generate each dao Proxy object for the interface.--> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <!--appoint SqlSessionFactory Object id--> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/> <!--Specify the package name, which is dao The name of the package where the interface is located. MapperScannerConfigurer It will scan all interfaces in the package and execute each interface once getMapper()Method to get the of each interface dao Object. Created dao Object into spring In the container. dao The default name of an object is the initial lowercase of the interface name --> <property name="basePackage" value="com.changsha.dao"/> </bean> <!--statement service--> <bean id="buyService" class="com.changsha.service.Impl.BuyGoodsServiceImpl"> <property name="goodsDao" ref="goodsDao"/> <property name="saleDao" ref="saleDao"/> </bean> <!--Claim transaction manager--> <bean id="tansactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="myDataSource"/> </bean> <!--2.Declare the transaction attributes of the business method (isolation level, propagation behavior, timeout) id:Custom name, indicating <tx:advice> and </tx:advice>Configuration content between transaction-manager:Of the transaction manager object id --> <!--Imported advice Is the package name tx ending--> <tx:advice id="myAdvice" transaction-manager="tansactionManager"> <!--tx:attributes: Configure transaction properties--> <tx:attributes> <!--tx:method: Configure transaction attributes for specific methods, method There can be multiple methods, and the transaction attributes can be set for different methods name:Method name, 1) complete method name without package and class. 2)Wildcard methods can be used,* Represents any character propagation: Propagation behavior, enumeration value isolation: Isolation level rollback-for: The exception class name you specified, fully qualified class name. If an exception occurs, it must be rolled back --> <tx:method name="buy" propagation="REQUIRED" isolation="DEFAULT" rollback-for="java.lang.NullPointerException,com.bjpowernode.excep.NotEnoughException"/> <!--Use wildcards to specify many methods--> <tx:method name="add*" propagation="REQUIRES_NEW" /> <!--Specify modification method--> <tx:method name="modify*" /> <!--Delete method--> <tx:method name="remove*" /> <!--Query method, query,search,find--> <tx:method name="*" propagation="SUPPORTS" read-only="true" /> </tx:attributes> </tx:advice> <!--Note the imported aop Is it correct--> <aop:config> <aop:pointcut id="servicePt" expression="execution(* *..service..*.*(..))"/> <aop:advisor advice-ref="myAdvice" pointcut-ref="servicePt" /> </aop:config> </beans>
Step 9: method test
package com.changsha; import com.changsha.service.BuyGoodsService; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Mytest { @Test public void test(){ String config = "applicationContext.xml"; ApplicationContext ctx = new ClassPathXmlApplicationContext(config); BuyGoodsService buyGoodsService = (BuyGoodsService) ctx.getBean("buyService"); //Becomes the object of a dynamic proxy System.out.println(buyGoodsService.getClass().getName()); buyGoodsService.buy(1001,10); } }