spring中的事物
Posted zy-sai
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spring中的事物相关的知识,希望对你有一定的参考价值。
spring中的事物
【1】事物的概念
事务的概念:事务指的是逻辑上的一组操作,这组操作要么全部成功,要么全部失败。
【2】事务的特性
原子性(Atomicity):当事务结束,它对所有资源状态的改变都被视为一个操作,这些操作要不同时成功,要不同时失败;
一致性(Consistency):操作完成后,所有数据必须符合业务规则,否则事务必须中止;
隔离性(Isolation):事务以相互隔离的方式执行,事务以外的实体无法知道事务过程中的中间状态;
持久性(Durable):事务提交后,数据必须以一种持久性方式存储起来。
【3】不考虑事务引发的安全
(1)脏读:一个事务读取了另一个事务改写但还未提交的数据,如果这些数据被回滚,则读到的数据是无效的。
(2)不可重复读:在同一个事务中,多次读取同一数据返回的结果有所不同。
(3)幻读:一个事务读取了几行记录后,另一个事务插入一些记录,幻读就发生了。再后来的查询中,第一个事务就会发现有些原来没有的记录。
【4】spring的事物管理机制
Spring事物管理高层抽象主要包括三个接口,spring的失误主要是由他们共同完成的:
PlatformTransactionManager 事务管理器(提交、回滚事务)
TransactionDefinition 事务定义信息(隔离、传播、超时、只读)
TransactionStatus 事务具体运行状态
【5】PlatformTransactionManager接口
PlatformTransactionManager 该接口提供了三个方法:
commit:提交事物
rollback:回滚事物
getTransaction:获取事物的状态
Spring为不同的持久性框架提供了不同的 PlatformTransactionManager 接口实现:
SpringJDBC 或 iBatis 框架:
org.springframework.jdbc.datasource.DataSourceTransactionManager
hibernate:
org.springframework.orm.hibernate3.HibernateTransactionManager
org.springframework.orm.hibernate4.HibernateTransactionManager
org.springframework.orm.hibernate5.HibernateTransactionManager
JPA:
org.springframework.orm.jpa.JpaTransactionManager
JDO:
org.springframework.orm.jdo.JdoTransactionManager
JTA:
org.springframework.transaction.jta.JtaTransactionManager
org.springframework.jdbc.datasource.DataSourceTransactionManager针对JDBCTemplate,Mybatis,使用Connection进行事物控制:
开启事物:connection.setAutoCommit(false);
提交事物:connection.commit();
回滚事物:connection.rollback();
【6】TransactionDefinition接口
事务隔离级别(五种):
隔离级别 :含义
default :使用后端数据库默认的隔离级别(spring中的选择项)
read_uncommited: 允许你读取还未提交的改变了的数据。可能导致脏、幻、不可重复读
read_committed :允许在并发事务已经提交后读取。可防止脏读,但幻读和不可重复读仍可发生
repeatable_read: 对相同字段的多次读取是一致的,除非数据被事务本身改变。可防止脏、不可重复读,但幻读仍可能发生
serializable :完全服从acid的隔离级别,确保不发生脏、幻、不可重复读。这在所有的隔离级别中是最慢的,它是典型的通过完全锁定在事务中涉及的数据表来完成的
注: 其中,mysql默认采用repeatable_read隔离级别;oracle默认采用read_committed隔离级别
七种事务传播行为:
事务传播行为 :含义
required :支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
supports :支持当前事务,如果当前没有事务,就以非事务方式执行
mandatory :支持当前事务,如果当前没有事务,就抛出异常。
requires_new :以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
not_supported: 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
never :以非事务方式执行,如果当前存在事务,则抛出异常。
nested: 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与required类似的操作。拥有多个可以回滚的保存点,内部回滚不会对外部事务产生影响。只对datasourcetransactionmanager有效。
【7】TransactionStatus接口
TransactionStatus接口用来记录事务的状态。该接口定义了一组方法,用来获取或判断事务的相应状态信息。
平台事务管理器(PlatformTransactionManager)会根据TransactionDefinition中定义的事务信息(包括隔离级别、传播行为)来进行事务的管理,在管理的过程中事务可能产生了保存点或事务是新的事务等情况,那么这些信息都会记录在TransactionStatus的对象中。
【8】事务超时/回滚规则
事务超时 :
为了使应用程序很好地运行,事务不能运行太长的时间。因为事务可能涉及对后端数据库的锁定,所以长时间的事务会不必要的占用数据库资源。事务超时就是事务的一个定时器,在特定时间内事务如果没有执行完毕,那么就会自动回滚,而不是一直等待其结束。
回滚规则 :
事务五边形的最后一个方面是一组规则,这些规则定义了哪些异常会导致事务回滚而哪些不会。默认情况下,事务只有遇到运行期异常时才会回滚,而在遇到检查型异常时不会回滚(这一行为与EJB的回滚行为是一致的)。但是你可以声明事务在遇到特定的检查型异常时像遇到运行期异常那样回滚。同样,你还可以声明事务遇到特定的异常不回滚,即使这些异常是运行期异常。
【9】业务中的事物案例
业务1:取款是一个事物操作,打印凭条是一个事物
业务2:删除客户信息之后,同时需要删除用的订单信息,一个事物。 //客户信息删除了,订单信息就多余了
【9】基于xml配置声明式事物
CREATE TABLE `account` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) NOT NULL,
`money` double DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
INSERT INTO `account` VALUES (‘1‘, ‘aaa‘, ‘1000‘);
INSERT INTO `account` VALUES (‘2‘, ‘bbb‘, ‘1000‘);
INSERT INTO `account` VALUES (‘3‘, ‘ccc‘, ‘1000‘);
package com.tencent.mapper; import org.apache.ibatis.annotations.Param; public interface AccountMapper { void outMoney(@Param("money") double money ,@Param("name") String name); void inMoney(@Param("money") double money ,@Param("name")String name); }
<?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"> <mapper namespace="com.tencent.mapper.AccountMapper"> <resultMap type="People" id="people"> <id column="id" property="id" /> <result column="name" property="name" /> <result column="money" property="money" /> </resultMap> <!-- 转出 --> <update id="outMoney" > update account set money=money-#{money} where name=#{name}; </update> <!-- 转入 --> <update id="inMoney" parameterType="People"> update account set money=money+#{money} where name=#{name}; </update> </mapper>
package com.tencent.pojo; public class People { private int id; private String name; private double money; 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 double getMoney() { return money; } public void setMoney(double money) { this.money = money; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + id; long temp; temp = Double.doubleToLongBits(money); result = prime * result + (int) (temp ^ (temp >>> 32)); result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; People other = (People) obj; if (id != other.id) return false; if (Double.doubleToLongBits(money) != Double.doubleToLongBits(other.money)) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } @Override public String toString() { return "People [id=" + id + ", name=" + name + ", money=" + money + "]"; } public People(int id, String name, double money) { super(); this.id = id; this.name = name; this.money = money; } public People() { super(); } }
package com.tencent.service; public interface AccountService { /** * * @方法的说明: * @author 张瑛 * @Time 2019年5月18日 下午6:52:22 * @param outName 转出人姓名 * @param inMoney 转入人姓名 * @param money 转账金额 */ public void transfer(String outName,String inMoney ,double money); }
package com.tencent.service.impl; import com.tencent.mapper.AccountMapper; import com.tencent.service.AccountService; public class AccountServiceImpl implements AccountService { AccountMapper accountMapper; @Override public void transfer(String outName, String inName, double money) { accountMapper.outMoney(money, outName); //异常 //int i=1/0; accountMapper.inMoney(money, inName); } public AccountMapper getAccountMapper() { return accountMapper; } public void setAccountMapper(AccountMapper accountMapper) { this.accountMapper = accountMapper; } }
package com.tencent.test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.tencent.service.AccountService; public class TransactionTest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationcontext.xml"); AccountService bean = (AccountService) context.getBean("accountServiceImpl"); bean.transfer("aaa", "bbb", 100d); } }
<?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: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/context http://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 http://www.springframework.org/schema/aop/spring-aop.xsd" default-autowire="byName"> <!-- 配置属性文件 --> <context:property-placeholder location="classpath:db.properties"/> <!-- 配置业务层类 --> <bean id="accountServiceImpl" class="com.tencent.service.impl.AccountServiceImpl"> <property name="accountMapper" ref="accountMapper"></property> </bean> <!-- 配置数据源 --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="${mysql.driver}"/> <property name="url" value="${mysql.url}"/> <property name="username" value="${mysql.username}"/> <property name="password" value="${mysql.password}"/> </bean> <!-- 配置工厂 --> <bean id="factory" class="org.mybatis.spring.SqlSessionFactoryBean"> <!-- 配置别名 --> <property name="typeAliasesPackage" value="com.tencent.pojo"></property> </bean> <!-- 配置mapper扫描 --> <bean id="mapper" class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="sqlSessionFactoryBeanName" value="factory"></property> <property name="basePackage" value="com.tencent.mapper"></property> </bean> <!-- ****************************************配置声明式事物******************************************* --> <!-- 配置事物管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 配置事物通知 --> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <!-- 配置事物管理策略 --> <tx:attributes> <!-- 需要配增强的方法 --> <tx:method name="transfer" read-only="false" isolation="DEFAULT" propagation="REQUIRED"/> </tx:attributes> </tx:advice> <!-- 配置切面 --> <aop:config> <!-- 配置切入点 --> <aop:pointcut expression="bean(*ServiceImpl)" id="mycut"/> <!-- <aop:pointcut expression="execution(* com.tencent.service.*.*(..))" id="poi"/> --> <!-- 配置切面 --> <aop:advisor advice-ref="txAdvice" pointcut-ref="mycut"/> </aop:config> </beans>
mysql.driver=com.mysql.jdbc.Driver
mysql.url=jdbc:mysql://127.0.0.1:3306/ssm?characterEncoding=utf8
mysql.username=root
mysql.password=root
# Set root category priority to INFO and its only appender to CONSOLE.
log4j.rootCategory=error, CONSOLE,LOGFILE
log4j.logger.com.bjsxt.mapper.FlowerMapper=debug
log4j.logger.com.bjsxt.controller.MyContorlller=debug
# CONSOLE is set to be a ConsoleAppender using a PatternLayout.
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%c-%d{yyyy/MMM/dd HH:mm:ss}- %m%n
# LOGFILE is set to be a File appender using a PatternLayout.
log4j.appender.LOGFILE=org.apache.log4j.FileAppender
log4j.appender.LOGFILE.File=D:/axis.log
log4j.appender.LOGFILE.Append=true
log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.LOGFILE.layout.ConversionPattern=%c-%d{yyyy/MMM/dd HH:mm:ss}- %m%n
<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.tencent</groupId> <artifactId>SSM_001</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <!-- 自定义属性标签 --> <properties> <servlet-version>3.0.1</servlet-version> <jsp-version>2.2</jsp-version> <jstl-version>1.2</jstl-version> <spring-version>4.1.6.RELEASE</spring-version> <aspectjweaver-version>1.8.6</aspectjweaver-version> <mybatis-version>3.2.7</mybatis-version> <mybatis-spring-version>1.2.3</mybatis-spring-version> <log4j-version>1.2.17</log4j-version> <mysql-connector-java-version>5.1.38</mysql-connector-java-version> <jackson-version>2.4.3</jackson-version> <commons-fileupload-version>1.3.1</commons-fileupload-version> <tomcat-version>2.2</tomcat-version> <dubbo-version>2.5.3</dubbo-version> <zkClient-version>0.10</zkClient-version> <ftpclient-version>3.3</ftpclient-version> <jedis-version>2.8.1</jedis-version> <ego-version>0.0.1-SNAPSHOT</ego-version> <httpclient-version>4.4.1</httpclient-version> <pagehelper-version>4.1.6</pagehelper-version> </properties> <dependencies> <!-- servlet --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>${servlet-version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>${jsp-version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>${jstl-version}</version> </dependency> <!-- spring --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring-version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring-version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring-version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>${spring-version}</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>${aspectjweaver-version}</version> </dependency> <!-- mybatis和spring整合 --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>${mybatis-spring-version}</version> </dependency> <!-- mybatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>${mybatis-version}</version> </dependency> <!-- log4j 日志 --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>${log4j-version}</version> </dependency> <!-- mysql 驱动类 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql-connector-java-version}</version> </dependency> <!-- jackson --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>${jackson-version}</version> </dependency> </dependencies> </project>
【10】基于注解配置声明式事物
CREATE TABLE `account` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(20) NOT NULL, `money` double DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8; INSERT INTO `account` VALUES (‘1‘, ‘aaa‘, ‘1000‘); INSERT INTO `account` VALUES (‘2‘, ‘bbb‘, ‘1000‘); INSERT INTO `account` VALUES (‘3‘, ‘ccc‘, ‘1000‘);
package com.tencent.mapper; import org.apache.ibatis.annotations.Param; public interface AccountMapper { void outMoney(@Param("money") double money ,@Param("name") String name); void inMoney(@Param("money") double money ,@Param("name")String name); }
<?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"> <mapper namespace="com.tencent.mapper.AccountMapper"> <resultMap type="People" id="people"> <id column="id" property="id" /> <result column="name" property="name" /> <result column="money" property="money" /> </resultMap> <!-- 转出 --> <update id="outMoney" > update account set money=money-#{money} where name=#{name}; </update> <!-- 转入 --> <update id="inMoney" parameterType="People"> update account set money=money+#{money} where name=#{name}; </update> </mapper>
package com.tencent.pojo; public class People { private int id; private String name; private double money; 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 double getMoney() { return money; } public void setMoney(double money) { this.money = money; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + id; long temp; temp = Double.doubleToLongBits(money); result = prime * result + (int) (temp ^ (temp >>> 32)); result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; People other = (People) obj; if (id != other.id) return false; if (Double.doubleToLongBits(money) != Double.doubleToLongBits(other.money)) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } @Override public String toString() { return "People [id=" + id + ", name=" + name + ", money=" + money + "]"; } public People(int id, String name, double money) { super(); this.id = id; this.name = name; this.money = money; } public People() { super(); } }
package com.tencent.service; public interface AccountService { /** * * @方法的说明: * @author 张瑛 * @Time 2019年5月18日 下午6:52:22 * @param outName 转出人姓名 * @param inMoney 转入人姓名 * @param money 转账金额 */ public void transfer(String outName,String inMoney ,double money); }
package com.tencent.service.impl; import java.util.List; import javax.annotation.Resource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import com.tencent.mapper.AccountMapper; import com.tencent.pojo.People; import com.tencent.service.AccountService; /** * @Transactional 用在类上对该类中的所有方法有效 用在某一个方法上只对该方法有效 */ @Service public class AccountServiceImpl implements AccountService { @Autowired AccountMapper accountMapper; @Transactional public void transfer(String outName, String inName, double money) { accountMapper.outMoney(money, outName); //异常 int i=1/0; accountMapper.inMoney(money, inName); } }
package com.tencent.test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.tencent.service.AccountService; public class TransactionTest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationcontext.xml"); AccountService bean = (AccountService) context.getBean("accountServiceImpl"); bean.transfer("aaa", "bbb", 100d); } }
<?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: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/context http://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 http://www.springframework.org/schema/aop/spring-aop.xsd" default-autowire="byName"> <!-- 配置属性文件 --> <context:property-placeholder location="classpath:db.properties"/> <!-- 配置业务层类 注解扫描 --> <context:component-scan base-package="com.tencent.service.impl"></context:component-scan> <!-- 配置数据源 --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="${mysql.driver}"/> <property name="url" value="${mysql.url}"/> <property name="username" value="${mysql.username}"/> <property name="password" value="${mysql.password}"/> </bean> <!-- 配置工厂 --> <bean id="factory" class="org.mybatis.spring.SqlSessionFactoryBean"> <!-- 配置别名 --> <property name="typeAliasesPackage" value="com.tencent.pojo"></property> </bean> <!-- 配置mapper扫描 --> <bean id="mapper" class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="sqlSessionFactoryBeanName" value="factory"></property> <property name="basePackage" value="com.tencent.mapper"></property> </bean> <!-- 配置事物管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 开启注解事务 --> <tx:annotation-driven transaction-manager="transactionManager"/> </beans>
mysql.driver=com.mysql.jdbc.Driver
mysql.url=jdbc:mysql://127.0.0.1:3306/ssm?characterEncoding=utf8
mysql.username=root
mysql.password=root
oracle.driver=oracle.jdbc.OracleDriver
oracle.url=jdbc:oracle:thin:@localhost:1521:orcl
oracle.username=scott
oracle.password=123456
# Set root category priority to INFO and its only appender to CONSOLE.
log4j.rootCategory=error, CONSOLE,LOGFILE
log4j.logger.com.bjsxt.mapper.FlowerMapper=debug
log4j.logger.com.bjsxt.controller.MyContorlller=debug
# CONSOLE is set to be a ConsoleAppender using a PatternLayout.
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%c-%d{yyyy/MMM/dd HH:mm:ss}- %m%n
# LOGFILE is set to be a File appender using a PatternLayout.
log4j.appender.LOGFILE=org.apache.log4j.FileAppender
log4j.appender.LOGFILE.File=D:/axis.log
log4j.appender.LOGFILE.Append=true
log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.LOGFILE.layout.ConversionPattern=%c-%d{yyyy/MMM/dd HH:mm:ss}- %m%n
<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.tencent</groupId> <artifactId>SSM_002</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <!-- 自定义属性标签 --> <properties> <servlet-version>3.0.1</servlet-version> <jsp-version>2.2</jsp-version> <jstl-version>1.2</jstl-version> <spring-version>4.1.6.RELEASE</spring-version> <aspectjweaver-version>1.8.6</aspectjweaver-version> <mybatis-version>3.2.7</mybatis-version> <mybatis-spring-version>1.2.3</mybatis-spring-version> <log4j-version>1.2.17</log4j-version> <mysql-connector-java-version>5.1.38</mysql-connector-java-version> <jackson-version>2.4.3</jackson-version> <commons-fileupload-version>1.3.1</commons-fileupload-version> <tomcat-version>2.2</tomcat-version> <dubbo-version>2.5.3</dubbo-version> <zkClient-version>0.10</zkClient-version> <ftpclient-version>3.3</ftpclient-version> <jedis-version>2.8.1</jedis-version> <ego-version>0.0.1-SNAPSHOT</ego-version> <httpclient-version>4.4.1</httpclient-version> <pagehelper-version>4.1.6</pagehelper-version> </properties> <dependencies> <!-- servlet --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>${servlet-version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>${jsp-version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>${jstl-version}</version> </dependency> <!-- spring --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring-version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring-version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring-version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>${spring-version}</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>${aspectjweaver-version}</version> </dependency> <!-- mybatis和spring整合 --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>${mybatis-spring-version}</version> </dependency> <!-- mybatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>${mybatis-version}</version> </dependency> <!-- log4j 日志 --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>${log4j-version}</version> </dependency> <!-- mysql 驱动类 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql-connector-java-version}</version> </dependency> <!-- jackson --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>${jackson-version}</version> </dependency> </dependencies> </project>
以上是关于spring中的事物的主要内容,如果未能解决你的问题,请参考以下文章