Spring
Javaweb —Spring
Spring closeout - transaction, web
The key to integrating mybatis in Spring is the three objects: Datasource object, SqlSessionFactory object and dao object created by mappercannerconfig - all are completed in the configuration file. druid does not need driver information
Spring transaction
- What is a transaction?
A transaction is actually a set of sql statements (usually DML) that complete business logic. There are multiple sql statements in the set, including UPDATE, INSERT, DELETE, etc. the characteristics of a transaction are ACID, atomic (atomicity), consistency (consistency) success or failure at the same time, isolation (isolation) and durability (persistence), which are executed as a whole.
- When to use transactions?
When the operation involves multiple tables or multiple DML statements, these statements modify the data in the table. In order to ensure data security, transactions need to be used to ensure the successful completion of the function at the same time, or fail to ensure security at the same time [transfer, cannot be increased or reduced]
- Where should transactions be handled in a program?
Transactions are originally in the Dao layer, but generally, transactions need to be raised to the business layer in order to use the characteristics of transactions to manage specific things. Because the service layer usually calls multiple Dao methods and executes multiple sql statements, transactions must be used to ensure data security
- How to use transactions in JDBC or Mybatis?
Write transactions separately on the console, start transactions, rollback or commit; There are also four isolation levels for transactions. mysql defaults to repeatable; JDBC accesses the database and uses the Connection object to execute transactions. At first, setAutoCommit is false; Then finally commit; Rollback in catch; In mybatis, the sqlSession object is used to handle transactions, such as rollback; The previous consolidation process did not highlight transactions because transactions were automatically committed
Different database access technologies have different objects and methods to deal with transactions, such as JDBC and Mybatis, and access the transaction principle used by database access technology. Master the processing logic in various databases, when to commit transactions, roll back transactions, and processing methods.
The first mock exam technology is a multi database access technology, and there are different mechanisms and objects for mechanism handling. Spring provides a unified model for transaction processing [transaction normalization], and uses a unified procedure to accomplish transaction processing of different database access technologies, such as mybatis, hibernate and other database access technologies -- -- > spring transaction processing model: defines all aspects of transaction processing and defines the most basic processing steps [normalization]. Just like AOP, declarative transactions: provide transaction related resources and contents to spring and spring to process transaction submission and rollback, and there is almost no need to write code
In the Spring framework, there are two ways to implement things:
- Manage transactions using Spring's transaction annotations
- Manage transactions using AspectJ's AOP configuration
Spring transaction management
Spring transaction management mainly relies on two important interfaces
PaltformTransactionManager
As mentioned above, it is only necessary to hand over the transaction resources to spring, so the transaction submission and rollback depend on the transaction manager object instead of completing rollback and commit; Transaction manager is an interface and many implementation classes: namely, the PaltformTransactionManager interface and its implementation class: spring has created the transaction processing classes corresponding to each database access technology
If you use mybatis to access the database -------- > spring creates the data source transaction manager
If hibernate is used to access the database - > the spring ship is hibernate transaction manager
Although you do not need to create your own class, you need to tell Spring which technology is used. Here, you only need to declare the transaction manager implementation class in the configuration file using the bean tag. If you use mybatis, then
<bean id="xxx" class="......DataSourceTransactionManager"/>
TransactionDefinition
In addition to telling spring what to use, you also need to tell the type of transaction. The TransactionDefinition interface defines constants related to the transaction description, including the isolation level, propagation behavior, default delay time limit, operation, etc. the described transaction information includes
-
ISOLATION level of transactions: the spring framework uses several integer constants. It starts with ISOLATION, and mysql defaults to REPEATABLE_READ; oracle is READ_COMMITED
- ISOLATION_ READ_ Uncommitted: read uncommitted, no concurrency issues resolved
- ISOLATION_ READ_ Committed: the read has been committed, with non repeatability and unreal read
- ISOLATION_REAPTABLE_READ: repeatable, dirty read resolved, non repeatable, but phantom read exists
- ISOLATION_ Serializable: serialization. There is no problem of concurrency
-
Transaction timeout: indicates the maximum execution time of a method. If the method execution time exceeds the time, the transaction will be rolled back in seconds. Generally, it is not set and the default timeout is used_ DEFAULT: -1
-
Transaction PROPAGATION behavior: it controls whether business methods have transactions, what kind of transactions (7) methods in different transactions call each other in the method stack, and business maintenance during execution. For example, the method doSome of transaction A calls the method doOther() of transaction B. the maintenance of the transaction during the call execution is called the PROPAGATION behavior of the transaction, and the PROPAGATION behavior of the transaction is added to the method. PROPAGATION behavior starts with PROPAGATION
- PROPAGATION_REQUIRED: required, the specified method must be executed within the transaction. If the current method has a transaction, it must join the current transaction. If not, a new transaction will be created. Is the default propagation behavior of Spring (the callee needs a transaction)
- PROPAGATION_SUPPORTED: supported: the method supports the current transaction (the callee supports the current transaction). If there is no transaction, you can also query whether there is a transaction or not
- PROPAGETION_REQUIRED_NEW: a new transaction will always be created, and the existing transaction will be suspended until the current transaction is executed
There are a few, just in the following picture, because the frequency of use is not high
[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-fSdKZelB-1641997236397)(C:\Users\OMEY-PC\Desktop\OIP-C.jpg)]
In addition to telling Spring how to access, there are also transaction related information, as well as the timing of transaction commit and rollback
When the business method is executed successfully, no exception is thrown. When the method is executed, spring will submit a commit transaction
When a runtime exception occurs in a business method, spring executes rollback and calls the rollback of the transaction manager
When a non runtime exception occurs in the business method, it needs to be handled. The main exception is the checked exception, and the transaction commit is submitted
As mentioned in another written test question here, exceptions are divided into RuntimeException and non runtime exception. Runtime exceptions cannot be compiled and checked out, and do not need to be handled in advance, such as NullPointerException; Non runtime exceptions, i.e. checked exceptions and errors, such as IOException and SQLException
Spring's transaction is a unified model. 1) That is, the transaction management interface PaltformTransactionManager transaction manager uses bean s to specify the access method. 2) Specify which classes and methods need to join the transaction. 3) specify the transaction information through the transaction definition, including isolation level, propagation behavior, timeout, etc
Transaction instance simulation
This example - > purchase goods, simulate users to place orders, add sales records to the order table, and reduce inventory from the goods table [in fact, it is a simulated transfer behavior]
First, create a database table. Create two tables, sale s record table and goods inventory table
CREATE TABLE sale( id INT PRIMARY KEY AUTO_INCREMENT, gid INT NOT NULL, nums INT, FOREIGN KEY(gid) REFERENCES goods(id) ) CREATE TABLE goods( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(80), amount INT, price DECIMAL )
Note that the floating point number stored by the computer is not accurate, so it is called floating point number, so the commodity price here adopts the fixed-point number DECIMAL
Then simply insert the data [generated here, no handwriting]
NSERT INTO `cfengbase`.`goods` (`id`, `name`, `amount`, `price`) VALUES ('1001', 'notebook', '70', '15.2'); INSERT INTO `cfengbase`.`goods` (`id`, `name`, `amount`, `price`) VALUES ('1002', 'soap', '80', '7.88');
After that, use spring to integrate mybatis to create this entity class. Here, use the previous pom instead of importing dependencies. Write from the data persistence layer to the business layer. Here, write the entity class first. Here are two tables to create two entity classes. Note that if you override the toString method, println will call the toString method of the parent Object by default, which is in the format of... @..., and you can't see the specific value
package cfeng.domain; public class Goods { private int id; private String name; private int amount; private float price; public Goods() { } public Goods(int id, String name, int amount, float price) { this.id = id; this.name = name; this.amount = amount; this.price = price; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAmount() { return amount; } public void setAmount(int 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 + '}'; } }
Another creation is the same. Next, start writing the dao layer, that is, the interface and the corresponding mapper file
package cfeng.dao; import cfeng.domain.Sale; public interface SaleDao { //Insert sales record public int insertSale(Sale sale); } <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org/DTD Mapper 3.0" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="cfeng.dao.SaleDao"> <insert id="insertSale"> INSERT INTO sale (gid,nums) VALUES (#{gid},#{nums}) </insert> </mapper>
The other interface is defined in the same way
package cfeng.dao; import cfeng.domain.Goods; public interface GoodsDao { //Update the inventory. Goods indicates the goods purchased this time public int updateGoods(Goods goods); //Query commodity information and primary key public Goods selectGoods(int id); } <?xml version="1.0" encoding="UTF-8" ?> <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org/DTD Mapper 3.0" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="cfeng.dao.GoodsDao"> <select id="selectGoods" resultType="cfeng.domain.Goods"> SELECT id,name,price,amount FROM goods WHERE id = #{id} </select> <update id="updateGoods"> <!-- Be careful not to write the wrong name, corresponding, and set Don't drop your table name--> UPDATE goods SET amount = amount - #{amount} WHERE id = #{id} </update> </mapper>
There is nothing to set for the main configuration file of mybatis. Now an alias and a mapper are set, and the environment is integrated into the datasource
<?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> <!-- This also starts from the root of the classpath because resource Copy directly to classes Next, write the name directly here--> <properties resource="db.properties"/> <settings> <setting name="logImpl" value="STDOUT_LOGGING"/> </settings> <typeAliases> <package name="cfeng.domain"/> </typeAliases> <!-- The future environment is used druid Yes --> <mappers> <!-- <mapper resource="cfeng\dao\StudentDao.xml"/>--> <package name="cfeng/dao"/> </mappers> </configuration>
In order to demonstrate that transactions will automatically roll back when encountering runtime exceptions, a class NotEnoughException is created here, which inherits the RuntimeException class and overrides the method
package cfeng.exception; public class NotEnoughException extends RuntimeException { public NotEnoughException() { super(); } public NotEnoughException(String message) { super(message); } }
Then simply write the service class to operate
package cfeng.service; public interface PurchaseGoods { //Define the method of purchasing goods. The parameters are the id and quantity of the purchased goods public void purchase(int goodsId, int amount); } package cfeng.service.impl; import cfeng.dao.GoodsDao; import cfeng.dao.SaleDao; import cfeng.domain.Goods; import cfeng.domain.Sale; import cfeng.exception.NotEnoughException; import cfeng.service.PurchaseGoods; public class PurchaseGoodsImpl implements PurchaseGoods { private SaleDao saleDao; private GoodsDao goodsDao;//Set method is established to facilitate the use of set injection of configuration file @Override public void purchase(int goodsId, int amount) { //Record sales records, relying on saledao //The object association table of entity class is not managed by spring container System.out.println("Business method start execution"); Sale saleRecord = new Sale(); saleRecord.setGid(goodsId); saleRecord.setNums(amount); saleDao.insertSale(saleRecord); //Update kucen and rely on goodsdao ---- > throw an exception here to make it easier to see the rollback Goods goods = goodsDao.selectGoods(goodsId); if(goods == null) { throw new NullPointerException("Item number is" + goodsId +"Your item does not exist"); }else if(goods.getAmount() < amount) { throw new NotEnoughException("Item number is" + goodsId +"Insufficient inventory of goods"); } Goods purchasegoods = new Goods(); purchasegoods.setId(goodsId); purchasegoods.setAmount(amount); goodsDao.updateGoods(purchasegoods); System.out.println("Business method successfully executed"); } public void setSaleDao(SaleDao saleDao) { this.saleDao = saleDao; } public void setGoodsDao(GoodsDao goodsDao) { this.goodsDao = goodsDao; } } //To facilitate viewing, prompt output is performed at the beginning and end of the method
Here, in order to facilitate viewing the rollback of runtime exceptions, exceptions are thrown between two sql operations
Next, write a test method; Using TRUNCATE can avoid self increasing discontinuities after deletion
@Test public void testMybatis() { //To read the property configuration file of spring, create a container ApplicationContext springContainer = new ClassPathXmlApplicationContext("applicationContext.xml"); PurchaseGoods purchase = (PurchaseGoods) springContainer.getBean("studentService"); // Arrays.stream(springContainer.getBeanDefinitionNames()).forEach(System.out::println); purchase.purchase(1001,1); }
Simple test
Business method start execution Creating a new SqlSession SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7adf16aa] was not registered for synchronization because synchronization is not active JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@768ccdc5] will not be managed by Spring ==> Preparing: INSERT INTO sale (gid,nums) VALUES (?,?) ==> Parameters: 1001(Integer), 1(Integer) <== Updates: 1 Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7adf16aa] Creating a new SqlSession SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@303e3593] was not registered for synchronization because synchronization is not active JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@768ccdc5] will not be managed by Spring ==> Preparing: SELECT id,name,price,amount FROM goods WHERE id = ? ==> Parameters: 1001(Integer) <== Columns: id, name, price, amount <== Row: 1001, notebook, 13, 30 <== Total: 1 Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@303e3593] Creating a new SqlSession SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3b9d6699] was not registered for synchronization because synchronization is not active JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@768ccdc5] will not be managed by Spring ==> Preparing: UPDATE goods SET amount = amount - ? WHERE id = ? ==> Parameters: 1(Integer), 1001(Integer) <== Updates: 1 Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3b9d6699] Business method successfully executed
The log is deliberately opened here to clear the opening and closing of the sqlsession object
Test out of stock after deleting data
Business method start execution cfeng.exception.NotEnoughException: The inventory of item No. 1001 is insufficient View database tables mysql> SELECT * FROM sale; +----+------+------+ | id | gid | nums | +----+------+------+ | 1 | 1001 | 1000 | +----+------+------+ 1 row in set (0.00 sec however goods The quantity of goods in the table has not decreased ----> Business chaos caused by not opening transactions
Add transaction to business method
Annotation @ Transactional
spring provides transaction processing methods. The first method is to add transactions through AOP mechanism annotation and add transactions with annotation @ Transactional. This annotation is provided by the framework itself and placed on the top of the public method, indicating that the current method has transactions, and the attribute of the annotation can be assigned to indicate the specific isolation level
Through annotation, transactions can be placed in the corresponding public method and managed in advance. All optional attributes are as follows
- Propagation: used to set the propagation attribute of transactions. The attribute is the enumeration of propagation. The default is PROPAGATION_REQUIRED
- Isolation: used to set the isolation times of transactions. It is also an enumeration of isolation. The default value is isolation DEFAULT
- readOnly: used to set whether the operation of this method on the database is read-only. The attribute is boolean, and the default is false [when the query operation of the database can be set to true; it can improve efficiency - read-only will be safer, but of course it will be slower]
- Timeout: sets the timeout period for the connection between this operation and the database. The unit is seconds. It is of type int. the default is - 1
- rollbackFor: Specifies the exception Class to be rolled back. The type is Class []. By default, it is an empty array. There is only one exception Class, and the array can not be used
- rollbackForClassName: Specifies the class name of the exception class to be rolled back. The type is String. It is empty by default
To use annotation @ Transactional
- Declare the transaction management object, and the < bean > tag uses the data source transaction manager - mybatis
<!-- Declare a transaction manager object --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <!-- Information about the database to which you want to connect,Know which table to open transactions for --> <property name="dataSource" ref="myDataSource"/> </bean>
- Turn on the transaction annotation driver and tell the spring framework to use annotations to manage transactions [spring uses AOP mechanism to create proxy objects of the class where @ Transactional is located and add transaction functions to methods] - turn on transactions before the execution of business methods, roll back or commit transactions after execution, This is equivalent to using the @ Around annotation in AOP to annotate the aspect class
//Simulate, just like before using JDBC to manage transactions @Around(......) public void ......(){ //Open transaction try{ Execute business methods; Commit transactions; commit }catch(Exception e){ ...... Rollback transaction rollback; } } --------------------Configuration in file------------------- Note: transaction transaction Abbreviated as tx,So I want to join spring-tx Rely on[ jdbc Is the foundation, so we should also add]--- <!-- Turn on the transaction annotation driver and tell spring Use annotation to manage transactions [scan] and create proxy objects annotation-driven Property is the transaction manager object, which is passed in id Note that you must select the correct namespace. There are multiple namespaces to select tx[transaction [abbreviation] space, you can see that the preparation is the same as that of the aspect class, and the notification symbol appears --> <tx:annotation-driven transaction-manager="transactionManager"/>
- Annotate the method @ Transactional
@Transactional( propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, readOnly = false, rollbackFor = {NullPointerException.class,NotEnoughException.class} ) @Override public void purchase(int goodsId, int amount) {
This is the transaction processing using the AOP method
//Methods for executing test classes System.out.println(purchase); purchase.purchase(1001,1000); cfeng.service.impl.PurchaseGoodsImpl@72f46e16 Business method start execution cfeng.exception.NotEnoughException: The inventory of item No. 1001 is insufficient Query database table Empty set (0.00 sec) -----> Note transaction rollback has been performed. You can open the log to see Business method start execution Creating a new SqlSession Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@182f1e9a] JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@64f857e7] will be managed by Spring An exception occurred Releasing transactional SqlSession ----- The transaction was released and rolled back Transaction synchronization deregistering SqlSession Transaction synchronization closing SqlSession
It can be found from the log that the transaction is enabled [but the default is because synchronization is not active [or the previous automatic submission mechanism]
Business method successfully executed Transaction synchronization committing SqlSession ----- Transaction committed Transaction synchronization deregistering SqlSession Transaction synchronization closing SqlSession
By changing the quantity to a normal value, you can find that the execution is successful and the transaction is committed
Rollback is to clear the previous operation, but for Auto_ For increment, you can see the operation trace. The used ones can't be used anymore
mysql> SELECT * FROM sale; +----+------+------+ | id | gid | nums | +----+------+------+ | 4 | 1001 | 1 | | 6 | 1001 | 3 | | 8 | 1001 | 3 | +----+------+------+
Five of the eight operations failed to roll back
In fact, the above annotations don't need to be written so much, because they are basically default values and directly @ Transactional
@Transactional @Override public void purchase(int goodsId, int amount) {
This is also normal
Here's an explanation about rollback for
The spring framework will detect whether the exception thrown by the method is in the rollbackFor attribute value array. Once thrown, all exceptions in the rollbackFor list will be rolled back. Therefore, adding non runtime exceptions to the list will also be rolled back
If the exception thrown is not in the attribute, spring will check the type of the exception. If it is a runtime exception, it will be rolled back. If not, it will not be rolled back
Manage transactions using AspectJ's aop configuration
The disadvantage of using xml to configure transaction proxy is that each target class needs to configure transaction proxy. When there are too many target classes, the configuration will be very cumbersome; There are many classes and methods that need to configure transactions. Declare classes in the spring configuration file. In this way, business methods and transaction codes are completely separated; [all implemented in the configuration file]
The implementation must first have spring aspects dependencies
- Declare the transaction manager or configure the bean, and select the data source transaction manager
<!-- Declare a transaction manager object --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <!-- Information about the database to which you want to connect,Know which table to open transactions for --> <property name="dataSource" ref="myDataSource"/> </bean>
- The type of transaction required by the declaration method is the attribute of the transaction, including propagation behavior, isolation level, time limit, etc. [only one annotation driven method can be written into the annotation] Declaration notification advise
<!-- name The first is the complete method of the method, without packages and classes You can also use wildcards* How to: *Represents any character method Represents pointcut,section The properties of other things can be configured, rollbackFor The fully qualified name of the exception class name must be used --> <!-- id Custom, indicating the configuration content--> <tx:advice id="myadvise" transaction-manager="transactionManager"> <tx:attributes> <!--Represents the properties of the transaction to be configured method Is the method of action, the entry point --> <tx:method name="purchase" propagation="REQUIRED" isolation="DEFAULT" rollback-for="java.lang.NullPointerException,cfeng.exception.NotEnoughException"/> </tx:attributes> </tx:advice>
In actual project development, there may be many business methods. In order to facilitate the use of wildcards, the naming of general methods should follow certain rules
Add operation public void addXXX()
Modification...... modifyXXX()
Delete operation...... removeXXX
Query operation...... queryXXX()
In this way, wildcards can be used in the configuration file; Priority starts with the most precise
<tx:method name="add*" propagation="REQUIRED" isolation="DEFAULT"/>
- Configure aop: specify which classes need to create proxies
Because the advice tag of tx above only configures the name of the method and does not specify the package name and class name, aop needs to be used for labeling
<!-- to configure aop --> <aop:config> <!-- Configure the pointcut expression to indicate which classes need to apply transactions id Name of pointcut expression pointcut expression: indicates the pointcut expression--> <aop:pointcut id="servicePt" expression="execution(* *..service..*.*(..))"/> <!-- Configuring enhancers: associations pointcut And above advisce --> <aop:advisor advice-ref="myadvise" pointcut-ref="servicePt"/> </aop:config>
Be sure to enhance notification advice and pointcut expressions
The complete spring configuration file is
<?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:util="http://www.springframework.org/schema/util" 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/util https://www.springframework.org/schema/util/spring-util.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"> <!-- Declare data source Datasource ,The function is to connect to the database. You don't need to mybatis of environment;Information of the data source object's own database--> <!-- Connect Alibaba's Druid data source --> <context:property-placeholder location="classpath:db.properties"/> <bean id="myDataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.user}"/> <property name="password" value="${jdbc.pwd}"/> <property name="maxActive" value="20"/> </bean> <bean id="mySqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="myDataSource"/> <property name="configLocation" value="classpath:mybatis.xml"/> </bean> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="sqlSessionFactoryBeanName" value="mySqlSession"/> <property name="basePackage" value="cfeng.dao"/> </bean> <bean name="studentService" class="cfeng.service.impl.PurchaseGoodsImpl"> <property name="saleDao" ref="saleDao"/> <property name="goodsDao" ref="goodsDao"/> </bean> <!-- Declare a transaction manager object --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <!-- Information about the database to which you want to connect,Know which table to open transactions for --> <property name="dataSource" ref="myDataSource"/> </bean> <!-- id Custom, indicating the configuration content--> <tx:advice id="myadvise" transaction-manager="transactionManager"> <tx:attributes> <!--Represents the properties of the transaction to be configured method Is the method of action, the entry point --> <tx:method name="purchase" propagation="REQUIRED" isolation="DEFAULT" rollback-for="java.lang.NullPointerException,cfeng.exception.NotEnoughException"/> </tx:attributes> </tx:advice> <!-- to configure aop --> <aop:config> <!-- Configure the pointcut expression to indicate which classes need to apply transactions id Name of pointcut expression pointcut expression: indicates the pointcut expression--> <aop:pointcut id="servicePt" expression="execution(* *..service..*.*(..))"/> <!-- Configuring enhancers: associations pointcut And above advisce --> <aop:advisor advice-ref="myadvise" pointcut-ref="servicePt"/> </aop:config> </beans>
In this way, the test method is executed again, which is the same as above
Spring web
In an ordinary SE project, using the spring container, you can simply create a container object in the main method. ApplicationContext springContainer = new ClassPathXmlApplicationContext("config");
However, the web project runs on the tomcat server and cannot be configured in this way. Here, we use the previous Student to develop a simple web project
First, when creating a project, you should configure the template and select webapp