Mybatis + SPRINGMVC Transaction Management

Source: Internet
Author: User

SPRINGMVC supports declarative and programmatic transaction management, and here I am talking about declarative transactions, that is, through annotations @Transactional to use transactions.

Here is the jar package I used in this project: http://download.csdn.net/detail/liujan511536/9050079

This is the source of my project: http://download.csdn.net/detail/liujan511536/9050093

This is a Dynamic Web project.
First look at the config file, Web. XML, this file is in the webcontent/web-inf/directory:
<?xml version= "1.0" encoding= "UTF-8"? ><web-app xmlns:xsi= "Http://www.w3.org/2001/XMLSchema-instance" xmlns= "Http://java.sun.com/xml/ns/javaee" xsi:schemalocation= "Http://java.sun.com/xml/ns/javaee/http Java.sun.com/xml/ns/javaee/web-app_3_0.xsd "id=" webapp_id "version=" 3.0 "> <display-name>springmvc_ Mybatis</display-name> <welcome-file-list> <welcome-file>index.html</welcome-file> < Welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> < Welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> < welcome-file>default.jsp</welcome-file> </welcome-file-list> <listener> <listener-class > Org.springframework.web.context.ContextLoaderListener </listener-class> </listener> <!--read Myba TIS configuration file--<context-param><param-name>contextconfiglocation</param-name><paraM-value>classpath:mybatis-context.xml</param-value> </context-param> <servlet> < Servlet-name>springmvc</servlet-name> <servlet-class> Org.springframework.web.servlet.dispatcherservlet</servlet-class> <init-param> <!-- Load SPRINGMVC XML into Spring context container--<param-name>contextConfigLocation</param-name> <param-value  > <!--/web-inf/classes/application-context.xml--Classpath:application-context.xml </param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> < Servlet-name>springmvc</servlet-name> <url-pattern>*.html</url-pattern> </ Servlet-mapping></web-app>

Mybatix-context.xml:
<?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:p= "http://www.springframework.org/schema/p" xmlns:context= "Http://www.springframework.org/schema/context" xmlns:mvc= "Http://www.springframework.org/schema/mvc" 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 Http://www.springframework.org/schema/context /spring-context.xsd Http://www.springframework.org/schema/mvc Http://www.springframework.org/schema/mvc/sp         Ring-mvc.xsd Http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd HTTP://WWW.SPRINGFRAMEWORK.ORG/SCHEMA/AOP/HTTPWww.springframework.org/schema/aop/spring-aop.xsd "> <bean id=" config "class=" Org.springframework.beans.factory.config.PropertyPlaceholderConfigurer "> <property name=" Locations "> <list> <value>classpath:db-config.properties</value> </list> </property> </bean ><!--metabase DataSource--><bean id= "DataSource" class= "Org.apache.commons.dbcp.BasicDataSource" >< Property Name= "Driverclassname" value= "${jdbc.driverclass}"/><property name= "username" value= "${        Jdbc.username} "/><property name=" url "value=" ${jdbc.url} "/></bean><bean id=" TransactionManager " class= "Org.springframework.jdbc.datasource.DataSourceTransactionManager" > <property name= "DataSource" ref= " DataSource "/> </bean> <tx:annotation-driven transaction-manager=" TransactionManager "/><bean id=" Sqlsessionfactory "class=" Org.mybatis.spring.SqlSessionFactoryBean "><property name=" DataSource "ref="DataSource "/><property name=" Typealiasespackage "value=" com.liujan.entity "/></bean><bean class= "Org.mybatis.spring.mapper.MapperScannerConfigurer" ><property name= "Basepackage" value= "Com.liujan.mapper" /></bean></beans>

Application-context.xml:

<?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:p= "http://www.springframework.org/schema/p" xmlns:context= "Http://www.springframework.org/schema/context" xmlns:mvc= "Http://www.springframework.org/schema/mvc" 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 http: Www.springframework.org/schema/context/spring-context.xsd Http://www.springframework.org/schema/mvc http ://www.springframework.org/schema/mvc/spring-mvc.xsd HTTP://WWW.SPRINGFRAMEWORK.ORG/SCHEMA/AOP HTTP://WWW.SP Ringframework.org/schema/aop/spring-aop-2.0.xsd "> <context:component-scan base-package=" Com.liujan "> </context:component-scan><bean Class= "Org.springframework.web.servlet.view.InternalResourceViewResolver" p:prefix= "/web-inf/page/" p:suffix= ". JSP" ></bean></beans>


transaction cannot be rolled back due to container assembly order
when loading this web. xml file, spring will load the other files introduced in this file, here are the two files of Mybatis-context.xml and Application-context.xml, two files are in/ The webcontent/web-inf/classes/directory. But there is a problem here, that is, the loading of these two files is sequential. Spring will first load the file introduced in the Context-param tag, which is the mybatis-context.xml here, and then load the application-context.xml. When loading the Mybatis-context.xml, spring assembles the @controlle and @service containers and puts them in the spring container. And then load Application-context.xml, and spring will assemble instances of @service and @controller annotations into the spring container, At this point, however, because the @service and @controller containers were already assembled at the time of loading the mybatis-context.xml, the newly assembled container would overwrite the previous container, so that only the containers that were subsequently assembled were left in the spring container. This assembly sequence leads to a problem, Since my transaction is declared in the Mybatis-context.xml file, the service container in this file is a transactional capability, but the service container assembled here is replaced by the service container in the later application-context.xml, and the AP The service container in Plication-context.xml is not transactional, so the service in the spring container does not have the transaction capability at the end. It is easy to get caught up in a trap; many beginners, after following the online tutorial, have found that they cannot roll back or other issues in any way, often due to this situation. to solve this problem, you simply generate a service-only container in Mybatis-context.xml, and the service container is not generated in application-context.xml. Because the service is a property in the Controller class, the service is assembled first before the controller is assembled. In order to achieve the above purpose, since is loaded myabtis-context.xml first, after loading application-context.xml, so we just need to Myabtis-context.xml Assembly service, do not assemble controller, then assemble controller in Application-context.xml, do not assemble service. This will have to modify the Mybatis-context.xml and application-context.xml two files, the modified file is as follows: Mybatis-context.xml:
<?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:p= "http://www.springframework.org/schema/p" xmlns:context= "Http://www.springframework.org/schema/context" xmlns:mvc= "Http://www.springframework.org/schema/mvc" 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 Http://www.springframework.org/schema/context /spring-context.xsd Http://www.springframework.org/schema/mvc Http://www.springframework.org/schema/mvc/sp         Ring-mvc.xsd Http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd HTTP://WWW.SPRINGFRAMEWORK.ORG/SCHEMA/AOP/HTTPWww.springframework.org/schema/aop/spring-aop.xsd "> <!--do not assemble controller--<context:component-scan base -package= "Com.liujan" > <context:exclude-filter type= "annotation" expression= " Org.springframework.stereotype.Controller "/> </context:component-scan> <bean id=" config "class=" org. Springframework.beans.factory.config.PropertyPlaceholderConfigurer "> <property name=" Locations "> < list> <value>classpath:db-config.properties</value> </list> </property> </bean> <!--metabase DataSource--><bean id= "DataSource" class= "Org.apache.commons.dbcp.BasicDataSource" >< Property Name= "Driverclassname" value= "${jdbc.driverclass}"/><property name= "username" value= "${        Jdbc.username} "/><property name=" url "value=" ${jdbc.url} "/></bean><bean id=" TransactionManager " class= "Org.springframework.jdbc.datasource.DataSourceTransactionManager" > <property name= "datasource"ref=" DataSource "/> </bean> <tx:annotation-driven transaction-manager=" TransactionManager "/><be An id= "sqlsessionfactory" class= "Org.mybatis.spring.SqlSessionFactoryBean" ><property name= "DataSource" ref= " DataSource "/><property name=" Typealiasespackage "value=" com.liujan.entity "/></bean><bean class= "Org.mybatis.spring.mapper.MapperScannerConfigurer" ><property name= "Basepackage" value= "Com.liujan.mapper" /></bean></beans>




Application-context.xml
<?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:p= "http://www.springframework.org/schema/p" xmlns:context= "Http://www.springframework.org/schema/context" xmlns:mvc= "Http://www.springframework.org/schema/mvc" 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 http: Www.springframework.org/schema/context/spring-context.xsd Http://www.springframework.org/schema/mvc http ://www.springframework.org/schema/mvc/spring-mvc.xsd HTTP://WWW.SPRINGFRAMEWORK.ORG/SCHEMA/AOP HTTP://WWW.SP Ringframework.org/schema/aop/spring-aop-2.0.xsd "> <!--assembly controller, do not assemble service--><context: Component-scan base-package= "Com.liujan" ><contexT:include-filter type= "Annotation" expression= "Org.springframework.stereotype.Controller"/><context: Exclude-filter type= "Annotation" expression= "Org.springframework.stereotype.Service"/></context: Component-scan><bean class= "Org.springframework.web.servlet.view.InternalResourceViewResolver" p:prefix= "/ web-inf/page/"p:suffix=". JSP "></bean></beans>

The Web. XML content does not change.
2. We control the transaction in the service layer, when a function (assuming the function named Funa) is preceded by awhen @Transactional a tag, it means that the function has a transactional capability. So what happens when a transaction commits, and when does a transaction rollback? If a transaction is to be rolled back, a uncheck exception (such as RuntimeException) must be thrown inside the Funa function, and the exception cannot be try...catch within Funa, for example, In the UserService class, there is a function called Saveuser, which is used to insert a piece of data into the database:
@Transactional (propagation=propagation.required) public void Saveuser (User u) throws Exception{usermapper.insert (U); throw new RuntimeException ("hehe");}
When you run this function, you first insert the data into the database U, and then throw the runtimeexception exception, and this exception is not captured by the Saveuser function, so this exception will be detected by spring, the transaction will be rolled back, data insertion failure;However, if the exception is caught by Saveuser, then spring will not detect the exception, the transaction will not be rolled back, and the data will be inserted successfully, as follows:
@Transactional (propagation=propagation.required, rollbackfor=exception.class) public void Saveuser (User u) throws Exception{usermapper.insert (u); try {throw new RuntimeException ("hehe");} catch (Exception e) {//Todo:handle Exception} }

However, if the exception is called by the Saveuser function catch, the transaction will also be rolled back, for example, there is a method in UsercontrollerAddUser, the UserService Saveuser method is called in this method:
public void AddUser (String name, int stuid) {User U = new User (); U.setname (name); U.setstuid (stuid); try {Userservice.saveu Ser (u);} catch (Exception e) {//Todo:handle exceptione.printstacktrace ();}}
The transaction will also be rolled back.In summary, as long as the exception is not caught in the place where the exception was thrown, the transaction is rolled back even if the exception is caught in the subsequent function.
Another problem here is that the exception thrown is only the uncheck class, and if the transaction of the check class is not rolled back, the following:
@Transactional (propagation=propagation.required) public void Saveuser (User u) throws Exception{usermapper.insert (U); throw new Exception ("hehe");}
Transactions are not rolled back at this time.If you want the transaction to be rolled back when you run out of the check class exception, you canThe @Transactional declares a rollback when a check class exception is encountered, as follows:
@Transactional (propagation=propagation.required, rollbackfor=exception.class) public void Saveuser (User u) throws Exception{usermapper.insert (u); throw new Exception ("hehe");}


Last Words@Transactional the labelThe meaning of propagation:

REQUIRED: Supports the current transaction and creates a new transaction if there is no current transaction. This is the most common choice.

SUPPORTS: Supports the current transaction and is executed in a non-transactional manner if no transaction is currently in use.

MANDATORY: Supports the current transaction and throws an exception if there is no current transaction.

Requires_new: Creates a new transaction and suspends the current transaction if a transaction is currently present.

Not_supported: Executes the operation in a non-transactional manner, suspending the current transaction if a transaction is currently present.

Never: Executes in a non-transactional manner and throws an exception if a transaction is currently present.

NESTED: Supports the current transaction, executes a nested transaction if the current transaction exists, and creates a new transaction if there is no current transaction.







Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.

Mybatis + SPRINGMVC Transaction Management

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.