本篇文章为你整理了SSM保姆级从创建项目到使用,包括事务和设置回滚(ssm项目实战完整教程)的详细内容,包含有ssm如何实现 ssm项目实战完整教程 ssm项目怎么运行 ssm项目都用到了什么技术 SSM保姆级从创建项目到使用,包括事务和设置回滚,希望能帮助你了解 SSM保姆级从创建项目到使用,包括事务和设置回滚。
2.创建项目
负责将代理类记性扫描,扫描的是Mapper接口所在的包,这个是mybatis提供的,所以会去找SqlSessionFactory
2.1 mybaits和Spring整合的jar包
mybaits和 Spring整合的官网:http://mybatis.org/spring/zh/index.html
2.1.1 思路:
2.1.2 MyBatis-Spring
这个jar包是mybaits提供的。
2.2 mybatis和spring整合所需要的jar包
要和 Spring 一起使用 MyBatis,需要在 Spring 应用上下文中定义至少两样东西:一个SqlSessionFactory和至少一个数据映射器类。
在 MyBatis-Spring 中,可使用SqlSessionFactoryBean来创建SqlSessionFactory。 要配置这个工厂 bean,只需要把下面代码放在 Spring 的 XML 配置文件中:
beanid="sqlSessionFactory"
propertyname="dataSource"ref="dataSource"/
/bean
还需要 Spring对ORM框架支持的jar包
!-- Spring orm
Spring提供spring-orm提供orm框架相关的支持。支持Hibernate、iBatis和JPA等
--
dependency
groupId org.springframework /groupId
artifactId spring-orm /artifactId
version 5.2.20.RELEASE /version
/dependency
projectxmlns="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.hy /groupId
artifactId ssm01 /artifactId
version 0.0.1 /version
packaging war /packaging
properties
project.build.sourceEncoding UTF-8 /project.build.sourceEncoding
project.reporting.outputEncoding UTF-8 /project.reporting.outputEncoding
maven.compiler.encoding UTF-8 /maven.compiler.encoding
/properties
dependencies
!-- Spring core --
dependency
groupId org.springframework /groupId
artifactId spring-context /artifactId
version 5.2.20.RELEASE /version
/dependency
!-- Spring orm
Spring提供spring-orm提供orm框架相关的支持。支持Hibernate、iBatis和JPA等
--
dependency
groupId org.springframework /groupId
artifactId spring-orm /artifactId
version 5.2.20.RELEASE /version
/dependency
!-- spring-aspects会帮我们传递过来aspectjweaver--
dependency
groupId org.springframework /groupId
artifactId spring-aspects /artifactId
version 5.2.20.RELEASE /version
/dependency
!-- mybaits相关jar包 --
dependency
groupId org.mybatis /groupId
artifactId mybatis /artifactId
version 3.5.6 /version
/dependency
!-- mybaits和Spring整合包 --
dependency
groupId org.mybatis /groupId
artifactId mybatis-spring /artifactId
version 2.0.7 /version
/dependency
!-- https://mvnrepository.com/artifact/org.projectlombok/lombok --
dependency
groupId org.projectlombok /groupId
artifactId lombok /artifactId
version 1.18.20 /version
/dependency
!-- 数据库连接池 --
dependency
groupId com.alibaba /groupId
artifactId druid /artifactId
version 1.2.9 /version
/dependency
!-- 连接数据库驱动 --
dependency
groupId mysql /groupId
artifactId mysql-connector-java /artifactId
version 5.1.49 /version
/dependency
!-- Spring-Test --
dependency
groupId org.springframework /groupId
artifactId spring-test /artifactId
version 5.2.20.RELEASE /version
/dependency
!-- Junit测试 --
dependency
groupId junit /groupId
artifactId junit /artifactId
version 4.12 /version
scope test /scope
/dependency
!-- logback日志 --
dependency
groupId ch.qos.logback /groupId
artifactId logback-classic /artifactId
version 1.2.3 /version
/dependency
!-- MybatisEHCache整合包 --
dependency
groupId org.mybatis.caches /groupId
artifactId mybatis-ehcache /artifactId
version 1.2.1 /version
/dependency
/dependencies
build
plugins
!-- 指定jdk,防止update project --
plugin
groupId org.apache.maven.plugins /groupId
artifactId maven-compiler-plugin /artifactId
configuration
source 1.8 /source
target 1.8 /target
!-- 项目编码 --
encoding UTF-8 /encoding
/configuration
/plugin
/plugins
/build
/project
2.4 创建jdbc.properties 和 logback.xml日志文件
?xmlversion="1.0"encoding="UTF-8"?
configurationdebug="true"
!-- 指定日志输出的位置 --
appendername="STDOUT"
encoder
!-- 日志输出的格式 --
!-- 按照顺序分别是:时间、日志级别、线程名称、打印日志的类、日志主体内容、换行 --
pattern [%d{HH:mm:ss.SSS}] [%-5level] [%thread] [%logger] [%msg]%n /pattern
/encoder
/appender
!-- 设置全局日志级别。日志级别按顺序分别是:TRACE DEBUG INFO WARN ERROR FATAL --
!-- 指定任何一个日志级别都只打印当前级别和后面级别的日志。 --
rootlevel="INFO"
!-- 指定打印日志的appender,这里通过“STDOUT”引用了前面配置的appender --
appender-refref="STDOUT"/
/root
!-- 根据特殊需求指定局部日志级别 --
loggername="com.hy.mapper"level="DEBUG"/
loggername="com.hy.test"level="DEBUG"/
/configuration
2.5 首先建立spring和mybaits的配置的文件 spring-mybatis.xml
2.5.1 加载外部属性文件
2.5.2 配置数据源
?xmlversion="1.0"encoding="UTF-8"?
beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
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-4.3.xsd"
!-- 加载外部属性文件 --
context:property-placeholderlocation="classpath:jdbc.properties"/
!-- 配置数据源 --
beanid="druidDataSource"
propertyname="driverClassName"value="${jdbc.dev.driver}"/
propertyname="url"value="${jdbc.dev.url}"/
propertyname="username"value="${jdbc.dev.username}"/
propertyname="password"value="${jdbc.dev.password}"/
/bean
/beans
importorg.slf4j.LoggerFactory;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.test.context.ContextConfiguration;
importorg.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring-mybatis.xml")
publicclassTest01 {
@Autowired
privateDataSource dataSource;
privateLogger logger= LoggerFactory.getLogger(this.getClass());
@Test
publicvoidtestConnection() throwsSQLException {
Connection connection= dataSource.getConnection();
logger.debug(connection.toString());
}
}
3.配置SqlSessionFactoryBean
SqlSessionFactoryBean是由MyBatis提供的packageorg.mybatis.spring;
SqlSessionFactoryBean实现了 FactoryBean这个接口,
这个接口是由Spring提供的。
会调用 getObject方法得到一个 对象,这个对象是
类型的对象。
3.1 配置方式[风格1]
1)风格1:保留Mybaits全局配置文件(核心配置文件mybatis-config.xml)
3.1.1 创建Mybatis全局配置文件
?xmlversion="1.0"encoding="UTF-8"?
!DOCTYPEconfiguration
PUBLIC"-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd"
configuration
settings
!-- 数据库中的字段的_规则,转类中属性的驼峰标示写法 --
settingname="mapUnderscoreToCamelCase"value="true"/
/settings
/configuration
!-- 配置SqlSessionFactoryBean创建的是 sqlSessionFactory,但是通过sqlSessionFactory工厂类的对象给你SqlSession对象--
beanid="sqlSessionFactoryBean"
!-- 装配数据源 --
propertyname="dataSource"ref="druidDataSource"/
!-- 指定Mapper映射文件的位置 --
propertyname="mapperLocations"value="classpath:mappers/*Mapper.xml"/
!-- 指定 MyBatis 全局配置文件位置 --
propertyname="configLocation"value="classpath:mybatis-config.xml"/
/bean
3.1.3 配置Mapper接口类型的bean扫描器MapperScannerConfiguration
配置 Mapper接口类型的bean扫描器
!-- 配置 Mapper接口类型的bean扫描器 --
beanid="mapperScannerConfigurer"
propertyname="basePackage"value="com.hy.mapper"/
/bean
3.1.4 创建com.hy.bean.Emp EmpMapper接口 EmpMapper.xml映射文件
privateString empGender;
privateDouble empSalary; //用包装类有null值
//构造方法(去ID的)
publicEmp(String empName, String empPwd, String empGender, Double empSalary) {
super();
this.empName= empName;
this.empPwd= empPwd;
this.empGender= empGender;
this.empSalary= empSalary;
}
}
publicinterfaceEmpMapper {
abstractpublicEmp selectById(longempId);
abstractpublicintinsert(Emp emp);
abstractpublicintdeleteById(longempId);
abstractpublicintupdate(Emp emp);
abstractpublicintupdateByMap(Map String, Object paramMap);
abstractpublicInteger selectCount();
abstractpublicMap String, Object selectForMap(intempId);
abstractpublicList Emp selectAll();
abstractpublicintinsertWithKey(Emp emp);
}
?xmlversion="1.0"encoding="UTF-8"?
!DOCTYPEmapper
PUBLIC"-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd"
mappernamespace="com.hy.mapper.EmpMapper"
selectid="selectById"resultType="com.hy.bean.Emp"
select emp_id empId,emp_name empName,emp_pwd empPwd,emp_gender empGender , emp_salary empSalary
from sys_emp where emp_id = #{empId}
/select
/mapper
importorg.slf4j.LoggerFactory;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.test.context.ContextConfiguration;
importorg.springframework.test.context.junit4.SpringJUnit4ClassRunner;
importcom.hy.bean.Emp;
importcom.hy.mapper.EmpMapper;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring-mybatis.xml")
publicclassTest02 {
@Autowired
privateEmpMapper empMapper;
privateLogger logger= LoggerFactory.getLogger(this.getClass());
@Test
publicvoidtestEmpMapper () throwsSQLException {
Emp emp= empMapper.selectById(1);
logger.debug(emp.toString());
}
}
3.1 配置方式[风格2]
2)风格2:彻底舍弃Mybaits全局配置文件(核心配置文件mybatis-config.xml),所有的一切在spring的配置文件中配。
!-- 配置SqlSessionFactoryBean --
beanid="sqlSessionFactoryBean"
!-- 指定 MyBatis 全局配置文件位置 --
!-- property name="configLocation" value="classpath:mybatis-config.xml"/ --
!-- 舍弃mybatis-config全局配置文件,使用configuration属性 --
propertyname="configuration"
bean
propertyname="mapUnderscoreToCamelCase"value="true"/
/bean
/property
!-- 舍弃mybatis-config全局配置文件,使用typeAliasesPackage属性,配置实体bean的别名 --
propertyname="typeAliasesPackage"value="com.hy.bean"/
!-- 指定Mapper映射文件的位置 --
propertyname="mapperLocations"value="classpath:mappers/*Mapper.xml"/
!-- 装配数据源 --
propertyname="dataSource"ref="druidDataSource"/
/bean
3.2注意,扫描包的时候分开扫描
spring-mybaits.xml只扫描Service,
而Mapper是用mybatis自带的扫描器MapperScannerConfigurer扫描
3.3spring-mybatis.xml完整的配置
?xmlversion="1.0"encoding="UTF-8"?
beansxmlns="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 http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd"
!-- 在spring-mybatis中 扫描@Servie注解标识的组件 --
context:component-scanbase-package="com.hy.service"/
!-- 加载外部属性文件 --
context:property-placeholderlocation="classpath:jdbc.properties"/
!-- 配置数据源 --
beanid="druidDataSource"
propertyname="driverClassName"value="${jdbc.dev.driver}"/
propertyname="url"value="${jdbc.dev.url}"/
propertyname="username"value="${jdbc.dev.username}"/
propertyname="password"value="${jdbc.dev.password}"/
/bean
!-- 配置SqlSessionFactoryBean --
beanid="sqlSessionFactoryBean"
!-- 指定 MyBatis 全局配置文件位置 --
propertyname="configLocation"value="classpath:mybatis-config.xml"/
!-- 舍弃mybatis-config全局配置文件,使用configuration属性
property name="configuration"
bean
property name="mapUnderscoreToCamelCase" value="true"/
/bean
/property
--
!-- 舍弃mybatis-config全局配置文件,使用typeAliasesPackage属性,配置实体bean的别名
property name="typeAliasesPackage" value="com.hy.bean"/
--
!-- 指定Mapper映射文件的位置 --
propertyname="mapperLocations"value="classpath:mappers/*Mapper.xml"/
!-- 装配数据源 --
propertyname="dataSource"ref="druidDataSource"/
/bean
!-- 配置 Mapper接口类型的bean扫描器 --
beanid="mapperScannerConfigurer"
propertyname="basePackage"value="com.hy.mapper"/
/bean
/beans
?xmlversion="1.0"encoding="UTF-8"?
!DOCTYPEconfiguration
PUBLIC"-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd"
configuration
settings
!-- 数据库中的字段的_规则,转类中属性的驼峰标示写法 --
settingname="mapUnderscoreToCamelCase"value="true"/
/settings
/configuration
编程式的实现方式存在缺陷:
1)具体操作过程中,所有细节都需要程序员自己来完成,比较繁琐。
2)代码复用性不高:如果没有有效抽取出来,每次实现功能都需要自己编写代码,代码就没有得到复用。
5.声明式事务
既然事务控制的代码有规律可循,代码的结构基本是确定的,所以框架就可以将固定模式的代码抽取出来,进行相关的封装。
封装起来后,我们只需要在配置文件中进行简单的配置即可完成操作。
好处1:提高开发效率
好处2:消除了冗余的代码
好处3:框架会综合考虑相关领域中在实际开发环境下有可能遇到的各种问题,进行了健壮性、性能等各个方面的优化
编程式事务:自己写代码实现功能
声明式事务:通过配置让框架实现功能
5.1事务管理器
5.1.1Spring 5.2以前
5.1.2 从 Spring 5.2开始
PlatformTransactionManager 接口本身没有变化,它继承了 TransactionManager。TransactionManager接口中什么都没有,它的存在的意义是定义一个技术体系。
我们现在要使用的事务管理器是org.springframework.jdbc.datasource.DataSourceTransactionManager,将来整合 Mybatis 用的也是这个类。
5.2 DataSourceTransactionManager类中的主要方法:
doBegin():开启事务
doCommit():提交事务
doRollback():回滚事务
doSuspend():挂起事务
doResume():恢复挂起的事务
6.添加Service层
6.1EmpService接口 EmpServiceImpl实现类
publicinterfaceEmpService {
abstractpublicEmp listById(longempId);
}
@Service
publicclassEmpServiceImpl implementsEmpService{
@Autowired
privateEmpMapper empMapper;
publicEmp listById(longempId) {
Emp emp= empMapper.selectById(empId);
returnemp;
}
}
importorg.slf4j.LoggerFactory;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.test.context.ContextConfiguration;
importorg.springframework.test.context.junit4.SpringJUnit4ClassRunner;
importcom.hy.bean.Emp;
importcom.hy.service.EmpService;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring-mybatis.xml")
publicclassTest03 {
@Autowired
privateEmpService empService;
privateLogger logger= LoggerFactory.getLogger(this.getClass());
@Test
publicvoidtestEmpService() throwsSQLException {
Emp emp= empService.listById(1);
logger.debug(emp.toString());
}
}
publicinterfaceEmpMapper {
abstractpublicvoidupdateEmpNameById(@Param("empId") long empId, @Param("empName")String empName);
abstractpublicvoidupdateEmpSalaryById(@Param("empId") longempId, @Param("empSalary")Double empSalary);
abstractpublicEmp selectById(longempId);
}
?xmlversion="1.0"encoding="UTF-8"?
!DOCTYPEmapper
PUBLIC"-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd"
mappernamespace="com.hy.mapper.EmpMapper"
selectid="selectById"resultType="com.hy.bean.Emp"
select emp_id empId,emp_name empName,emp_pwd empPwd,emp_gender empGender , emp_salary empSalary
from sys_emp where emp_id = #{empId}
/select
!--
abstract public void updateEmpNameById(@Param("empId")long empId, @Param("empName")String empName);
abstract public void updateEmpSalaryById(@Param("empId")long empId, @Param("empSalary")Double empsalary);
--
updateid="updateEmpNameById"
update sys_emp set emp_name = #{empName} where emp_id = #{empId}
/update
updateid="updateEmpSalaryById"
update sys_emp set emp_salary = #{empSalary} where emp_id = #{empId}
/update
/mapper
publicinterfaceEmpService {
abstractpublicEmp listById(longempId);
abstractpublicinteidtEmp(Emp emp);
}
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.stereotype.Service;
importcom.hy.bean.Emp;
importcom.hy.mapper.EmpMapper;
importcom.hy.service.EmpService;
@Service
publicclassEmpServiceImpl implementsEmpService{
@Autowired
privateEmpMapper empMapper;
publicEmplistById(longempId) {
Emp emp= empMapper.selectById(empId);
returnemp;
}
@Override
publicinteidtEmp(Emp emp) {
empMapper.updateEmpNameById(emp.getEmpId(), emp.getEmpName());
empMapper.updateEmpSalaryById(emp.getEmpId(), emp.getEmpSalary());
return0;
}
}
importorg.slf4j.LoggerFactory;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.test.context.ContextConfiguration;
importorg.springframework.test.context.junit4.SpringJUnit4ClassRunner;
importcom.hy.bean.Emp;
importcom.hy.service.EmpService;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring-mybatis.xml")
publicclassTest03 {
@Autowired
privateEmpService empService;
privateLogger logger= LoggerFactory.getLogger(this.getClass());
@Test
publicvoidtestEmpService() throwsSQLException {
Emp emp= empService.listById(1);
logger.debug(emp.toString());
}
@Test
publicvoidtestEmpService2() throwsSQLException {
Emp emp= newEmp(1L, "范冰冰plus3", "fbbplus", "f", 1315d);
empService.eidtEmp(emp);
}
}
出现异常的情况
7.事务
7.1编程式事务
事务功能的相关操作全部通过自己编写代码来实现:
编程式的实现方式存在缺陷:
1)具体操作过程中,所有细节都需要程序员自己来完成,比较繁琐。
2)代码复用性不高:如果没有有效抽取出来,每次实现功能都需要自己编写代码,代码就没有得到复用。
7.2 声明式事务
既然事务控制的代码有规律可循,代码的结构基本是确定的,所以框架就可以将固定模式的代码抽取出来,进行相关的封装。
封装起来后,我们只需要在配置文件中进行简单的配置即可完成操作。
好处1:提高开发效率
好处2:消除了冗余的代码
好处3:框架会综合考虑相关领域中在实际开发环境下有可能遇到的各种问题,进行了健壮性、性能等各个方面的优化
编程式事务:自己写代码实现功能
声明式事务:通过配置让框架实现功能
7.3 事务管理器
7.3.1Spring 5.2以前
7.3.2 从 Spring 5.2开始
PlatformTransactionManager 接口本身没有变化,它继承了 TransactionManager。TransactionManager接口中什么都没有,它的存在的意义是定义一个技术体系。
我们现在要使用的事务管理器是org.springframework.jdbc.datasource.DataSourceTransactionManager,将来整合 Mybatis 用的也是这个类。
7.4 DataSourceTransactionManager类中的主要方法:
doBegin():开启事务
doCommit():提交事务
doRollback():回滚事务
doSuspend():挂起事务
doResume():恢复挂起的事务
事务的挂起和恢复,主要是事务传播行为所体现的。
8基于注解的声明式事务
事务通常都是加到业务逻辑层,针对XxxService类使用事务
8.1 配置声明式事务,需要添加新的依赖
!-- Spring orm
Spring提供spring-orm提供orm框架相关的支持。支持Hibernate、iBatis和JPA等
--
dependency
groupId org.springframework /groupId
artifactId spring-orm /artifactId
version 5.2.20.RELEASE /version
/dependency
Spring 持久化层支持的jar包,Spring在执行持久化操作与持久化技术进行整合过程中,需要使用orm,tx,jdbc三个jar包
导入orm包就可以通过maven的依赖传递把其他两个也导入进来。
8.2 给事务管理器装配一下数据源 。
beanid="transactionManager"
!-- 给事务管理器bean装配数据源,其他属性保持默认即可--
propertyname="dataSource" ref="druidDataSource"/
/bean
!-- 开启基于注解的声明式事务 --
tx:annotation-driventransaction-manager="transactionManager"/
8.4 给EmpServiceImpl方法上加上注解@Transactional
给XxxServiceImpl类的方法中加上 @Transactional 注解,Spring会自动的给这个方法加上事务。
8.6 完整的配置spring-mybaits.xml
?xmlversion="1.0"encoding="UTF-8"?
beansxmlns="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 http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd"
!-- 在spring-mybatis中 扫描@Servie注解标识的组件 --
context:component-scanbase-package="com.hy.service"/
!-- 加载外部属性文件 --
context:property-placeholderlocation="classpath:jdbc.properties"/
!-- 配置数据源 --
beanid="druidDataSource"
propertyname="driverClassName"value="${jdbc.dev.driver}"/
propertyname="url"value="${jdbc.dev.url}"/
propertyname="username"value="${jdbc.dev.username}"/
propertyname="password"value="${jdbc.dev.password}"/
/bean
!-- 配置SqlSessionFactoryBean --
beanid="sqlSessionFactoryBean"
!-- 指定 MyBatis 全局配置文件位置 --
propertyname="configLocation"value="classpath:mybatis-config.xml"/
!-- 舍弃mybatis-config全局配置文件,使用configuration属性
property name="configuration"
bean
property name="mapUnderscoreToCamelCase" value="true"/
/bean
/property
--
!-- 舍弃mybatis-config全局配置文件,使用typeAliasesPackage属性,配置实体bean的别名
property name="typeAliasesPackage" value="com.hy.bean"/
--
!-- 指定Mapper映射文件的位置 --
propertyname="mapperLocations"value="classpath:mappers/*Mapper.xml"/
!-- 装配数据源 --
propertyname="dataSource"ref="druidDataSource"/
/bean
!-- 配置 Mapper接口类型的bean扫描器 --
beanid="mapperScannerConfigurer"
propertyname="basePackage"value="com.hy.mapper"/
/bean
!-- 配置事务管理器 --
beanid="transactionManager"
!-- 装配数据源 --
propertyname="dataSource"ref="druidDataSource"/
/bean
!-- 开启基于注解的声明式事务 --
tx:annotation-driventransaction-manager="transactionManager"/
/beans
!-- 根据特殊需求指定局部日志级别 --
loggername="com.hy.mapper"level="DEBUG"/
loggername="com.hy.test"level="DEBUG"/
loggername="org.springframework.jdbc.datasource.DataSourceTransactionManager"level="DEBUG"/
8.6.2 通过日志观察事务
8.6.3 通过debug源码的模式观察事务
1)开启事务的方法:doBegin
2)提交事务的方法
3)回滚事务的方法
8.7 查询开启事务
8.7.1 创建一个EmpService EmpServiceImpl
publicinterfaceEmpService {
abstractpublicEmplistById(longempId);
}
importorg.springframework.stereotype.Service;
importorg.springframework.transaction.annotation.Transactional;
importcom.hy.mapper.EmpMapper;
importcom.hy.service.EmpService;
@Service
publicclassEmpServiceImpl implementsEmpService {
@Autowired
privateEmpMapper empMapper;
@Transactional
@Override
publicEmp listById(longempId) {
Emp emp= empMapper.selectById(empId);
returnemp;
}
}
释放链接
[org.springframework.jdbc.datasource.DataSourceTransactionManager] [Creating new transaction with name [com.hy.service.impl.EmpServiceImpl.listById]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,readOnly]
这里为了现实效果,所以为查询配置了事务。
9事务的属性,这些属性可以设置但不是必须设置
1)事务的只读属性
2)事务的超时属性
3)回滚和不回滚的异常
4)事务的隔离级别
5)事务传播行为
9.1事务属性:只读
对一个查询操作来说,如果我们把它设置成只读,就能明确告诉数据库,这个操作不涉及写(添加,删除,修改)操作,这样数据库就能够针对查询操作来进行优化。
readOnly并不是所有数据库都支持。
9.1.1 设置方式
@Transaction(readOnly = true) //readOnly = true把当前事务属性设置为只读,默认为false
9.1.2 针对增删改操作设置只读属性
只读事务的好处,作为ORM框架优化的暗号,保证读一致性,事务内不允许DML操作,否则报错
只读事务的场景,如统计,保证统计结果准确性。
只读事务里,也可以在只读事务里使用 select... for update
因为只读事务,所有查询都是在一个事务里,所以可以配合mysql的事务隔离级别理解一下
(比如,你的mysql隔离事务是RR的,那么在只读事务注解里,多次查询同一个表的范围数据, 结果是一致的,如果不是在同一个事务里,那么前后查询可能会读到的数据条数不一致,造成幻读),如果隔离级别是RC的,可以不用在只读事务里,因为每次查询都会读取到已提交的数据
10.1 生效原则
如果一个类中每一个方法上都使用了@Transactional注解,那么就可以将@Transactional注解提取到类上,反过来说:@Transactional注解在类级别上标记,会影响到类中的每一个方法。同时,类级别标记的@Transactional注解中设置的事务属性也会延续影响到方法执行时的事务属性。除非在方法上由设置了@Transactional注解。
对一个方法来说,离它最近的@Transactional注解中的事务属性设置生效。
10.2 用法举例
在类级别@Transactional注解中设置只读,这样类中所有的查询方法都不需要设置@Transactional注解了,因为对查询操作来说,其他属性通常不需要设置,所以使用公共设置即可。
然后在这个基础上,对增删改方法设置@Transactional注解readOnly属性为false。
11.事务的属性:超时
事务在执行过程中,有可能因为遇到某些问题,导致程序卡主,从而长时间占用数据库资源,大概的原因可能是因为程序运行出现了问题(Java或是MySQL)或是网络出现问题。
此时,这个很可能出问题的程序应该被执行回滚操作,撤销它已做的操作,事务回滚,把资源让出来,让其他正常程序可以执行。
总计:超时回滚,释放资源。别让一个事务占用一个资源太长的时间。
单位是秒。
12. 事务属性:回滚和不回顾你的异常
默认情况:只针对运行时异常进行事务回滚,编译时异常不回滚。
//抛出编译时异常,测试是否回滚
new FileInputStream(“xxxxx”); 方法后面throwsFileNotFoundException
将回滚的异常扩大到Exception的范围。
12.1 设置回滚的异常
12.2 设置不回滚的异常
12.3 回滚和不回滚异常同时设置
13. 事务属性:事务的隔离级别:
事务的隔离级别和事务的传播行。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。