MyBatis-Spring -- 集成
文档:http://www.mybatis.org/spring/index.html
Github:https://github.com/mybatis/spring
DBCP:DataBase Connection Pool,数据库连接池
JNDI:Java Naming and Directory Interface,Java命名和目录接口;给JNDI工具类提供一个资源配置,就可以得到资源的连接,例如数据库连接
JAT:Java Transaction API,JAT工具类提供跨数据库连接的事务管理能力
DTD:Document Type Definition,文档类型定义
XSD:XML Schema Definition,XML模式定义,用于代替DTD
xmlns:XML Namespaces,XML命名空间
一个框架所需的 xmlns和xsi:schemaLocation,在该框架的jar包下的 META-INF目录 中可以找到
术语
Mapper:SQL操作接口 的 子实例
Repository:DAO相关代码
Service:业务层,即调用Mapper的类
IDEA 配置 MyBatis-Spring
1、Maven增加依赖
<!-- 整合SpringMVC -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId> <!-- Spring连接数据库相关 -->
<version>5.0.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId> <!-- 整合MyBatis和Spring,包含SqlSessionFactoryBean、MapperFactoryBean -->
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId> <!-- 数据库连接池,包含BasicDataSource、TransactionInterceptor -->
<version>2.5.0</version>
</dependency>
<!-- 整合SpringBoot -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId> <!-- mysql需要在配置文件里配置时区,default-time-zone='+08:00' -->
<artifactId>mysql-connector-java</artifactId>
<version>8.0.16</version> <!-- 版本得跟mysql版本一致 -->
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.12</version>
</dependency>
MyBatis-Spring应用的组成
1-0、整合SpringMVC配置,spring-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource"> <!-- 数据源 -->
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/world"/>
<property name="username" value="root"/>
<property name="password" value="wowo000"/>
<property name="maxTotal" value="255"/> <!-- 最大连接数 -->
<property name="maxIdle" value="5"/> <!-- 最大等待连接中的数量 -->
<property name="maxWaitMillis" value="10000"/> <!-- 最大等待毫秒数-->
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="configLocation" value="classpath:mybatis-config.xml"/> <!-- 引入MyBatis基础配置,进而引入整个MyBatis应用 -->
</bean>
<bean id="mapperFactory" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="com.maven.hogen.CityMapper"/>
<property name="SqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
</beans>
1-1、整合SpringBoot配置,application.yml
spring:
datasource:
url: jdbc:mysql://localhost:3306/xm?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8
username: root
password: xxxx
driver-class-name: com.mysql.jdbc.Driver
type: com.zaxxer.hikari.HikariDataSource
hikari:
minimum-idle: 5
maximum-pool-size: 15
auto-commit: true
idle-timeout: 30000
pool-name: DatebookHikariCP
max-lifetime: 500000
connection-timeout: 30000
connection-test-query: SELECT 1
mybatis:
config-location: classpath:mybatis-config.xml
mapper-locations: classpath:mapper/*Mapper.xml
type-aliases-package: com.hong.xm.pojo
2、使用
@Autowired // 自动注入Mapper
private CityMapper cityMapper;
City city = cityMapper.getCity(1L);
事务
丢失更新
第一类丢失更新:事务A更新成功,事务B回滚,回滚到了事务A更新之前的状态,导致事务A的更新丢失;这种丢失已被数据库管理系统解决,即回滚不会回滚掉其他事务的更新
第二类丢失更新:事务A更新成功,事务B在A更新成功之前的基础上更新,导致事务A的更新丢失
隔离级别
脏读:dirty read,允许一个事务去读取另一个事务未提交的数据
出错场景:事务B在事务A更新的基础上进行更新,但后来A回滚了
读/写提交:read commit,一个事务只能读取另一个事务已经提交的数据
出错场景:事务A在事务B提交之前读取一条记录,事务B更新了这条记录,事务A在事务B提交之后再读取同一条记录,事务A两次读取的记录不一致。所以在这个隔离级别下,不可重复读取数据(unrepeatable read)
可重复读:repeatable read,事务之间对同一条数据库记录的读写,排队进行,而不会交叉进行
出错场景:事务A在事务B提交之前统计记录数,事务B增减了记录,在事务B提交之后再统计记录数,两次记录数不同。因此这种隔离级别下,会出现幻读(phantom read )
序列化:Serializable,事务之间对数据库的读写,排队进行,而不会交叉进行
MySQL支持对应的4个隔离级别:READ_UNCOMMITTED,READ_COMMITTED,REPEATABLE_READ(默认),SERIALIZABLE
隔离级别越高,并行能力越差
传播行为
一个方法的传播行为用来描述这个方法支不支持事务,以及是否新开事务
REQUIRED(默认):没有在事务内,则在新建子事务内执行
SUPPORTS:可以在事务内执行
MANDATORY:必须在事务内执行
REQUIRES_NEW:在新建子事务内执行
NOT_SUPPORTED:在事务内,则挂起事务,执行完后,再恢复事务
NEVER:不能在事务内执行
NESTED:嵌套事务,在REQUIRES_NEW的基础上,如果子事务发生回滚,不回滚父事务
Spring 数据库事务
事务模板TransactionTemplate,通过AOP自动为业务代码 获取连接、提交事务、回滚事务
事务管理器PlatformTransactionManager:事务模板持通过调用事务管理器,来完成事务提交、事务回滚
DataSourceTransactionManager:是PlatformTransactionManager的实现类
Spring 数据库事务 应用的组成
1-0、SpringMVC配置,spring-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<bean id="dataSource">同上</bean>
<bean id="sqlSessionFactory">同上</bean>
<!-- 扫描basePackage,为@Repository注解的接口创建子实例,并装载入容器 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.maven.hogen"/>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
<property name="annotationClass" value="org.springframework.stereotype.Repository"/>
</bean>
<!-- 扫描base-package,为@Service和@Component注解的类创建实例,并装载入容器 -->
<context:annotation-config/> <!-- 需要引入context命名空间 和 xsd -->
<context:component-scan base-package="com.maven.hogen"/>
<!-- 事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 启用注解驱动,即将事务模板应用于@Transactional注解的方法 -->
<tx:annotation-driven transaction-manager="transactionManager"/> <!-- 需要引入tx命名空间 和 xsd -->
</beans>
1-1、SpringBoot配置,给主类增加注解 @MapperScan("com.hong.xm.dao")
2、Mapper接口
@Repository // 把Mapper实例装载入容器
public interface CityMapper {
public City getCity(long id);
}
3、Service类
@Service
public class CityServiceImpl {
@Autowired // 自动注入Mapper
private CityMapper cityMapper = null;
// @Transactional只能注解 非static的public方法;方法里调用 @Async 方法,依然会阻塞事务提交
@Transactional(propagation = Propagation.REQUIRED,isolation=Isolation.READ_COMMITTED)
public City getCity(long id){
return cityMapper.getCity(1);
}
}
4、使用
@Autowired
private CityServiceImpl cityService = null;
City city = cityService.getCity(1L);