Spring和mybatis整合

Spring框架和mybatis的整合

mybatis是半自动化的一个持久层框架,而spring是一个整合型框架

如何将mybatis整合到spring中去呢?

1、创建项目,引入各自的相关JAR包
2、设计项目的包结构,以及类结构 (项目设计阶段) —垂直分块 水平分层
3、编写applicationContext.xml完成框架的整合

<!-- 第1步:开启spring容器的自动扫描功能 -->
<!-- 第2步:引入外部的数据库配置描述文件 -->
<!-- 第3步:配置数据源连接池:C3P0,DBCP2,DRUID -->
<!-- 第4步,配置SessionFactory -->
<!-- 第5步,配置MapperScanner -->
<!-- 第6步,配置事务管理器 -->
<!-- 第7步,配置spring管理事务的2种方式:编程式事务管理,声明式事务管理 -->
<!-- 第8步,开启切面动态代理支持 -->
事务:一个具有明确边界的,有序的执行过程,比如:张三给李四转钱5K,HTTP请求响应

四大特点(ACID):

原子性 Atomicity:事务是一个完整的过程,不可再分,要么统一成功,要么统一失败
一致性 Consistency:讲究的是数据的准确性  整个事务流转过程中,事务开始接收了多少数据,那么结束时就应该返回多少数据(质量守恒)
隔离性 Isolation:事务和事务之间是相互独立的,互不干扰的
持久性 Durability:事务一旦提交,那么事务中受到的影响就应该被持久化下来

事务分类:物理事务   逻辑事务
物理事务:就是指单次的数据库事务
逻辑事务:就是指单词的业务逻辑事务   
一般来说:一个逻辑事务,可能是由多个物理事务构成

事务的隔离级别:

可串行化 SERIALIZABLE 隔离级别最高,它相当于将事务进行排队,每次只让一个事务处理对应的数据,它不能保证你得到什么,但是一定能保证
 你得到是准确的。但是它的执行效率最差
 
可重复读  REPEATABLE_READ 隔离级别仅次于可串行化,它的执行效率提升了,但是数据的准确性降低了,它会引发一个问题:虚读|幻读  当A操作大量
 数据,B操作大量数据中的某一个小部分数据,A再次查询时,可能会给他造成一种虚幻的感觉
 
读已提交  READ_COMMITTED  隔离级别又要下一个档次了,它的数据准确性就更低了,它会引发一个最严重的问题: 不可重复读    当A在同一事务中,如果连续2次读取数据库,将发现数据获取的结果不一致,那是因为他在2次读的过程中,B已经将数据修改了,并做了提交

读未提交  READ_UNCOMMITTED  隔离级别最差,数据准确性最低,它的最严重问题:脏读    A可能会读取到B并没有提交的数据 ,去完成A的业务逻辑


4种隔离级别中,使用最为广泛的是:可重复读


事务的传播:

REQUIRED 表示调用者如果没有事务,则新创一个事务,如果有事务,就采用调用者的事务进行事务控制  (cud)
SUPPORTS 表示调用者如果有事务,那么则采用这个事务,如果没有事务,那么就使用非事务方式来进行事务控制 (r)

REQUIRES_NEW 表示不管调用者有没有事务,都新创一个新的事务,如果有事务,那么就把老事务挂起来
NOT_SUPPORTED 表示不管调用者是否有事务,都采用非事务方式来执行事务控制,如果有事务,那么就把老事务挂起来
MANDATORY 表示调用者一定要有事务,如果没有事务,那我就抛异常
NESTED 嵌套事务,如果调用者和被调用者都有事务正在执行,那么我就将被调用者的事务嵌套到调用者事务来,进行统一的事务控制
NEVER 表示调用者一定不能有事务,如果有事务,那么我就抛异常

配置文件

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
/*
 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"
	固定语句
*/
<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: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-3.0.xsd
						/**spring容器上下文/
						http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        /*切面*/
        http://www.springframework.org/schema/aop 
        http://www.springframework.org/schema/aop/spring-aop.xsd
        /*事务管理*/
         http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd">

	<!-- 第1步开启spring的自动扫描 -->
	<context:component-scan base-package="com.gezhi.smspring"></context:component-scan>
	<!-- 第2步导入外部数据库配置文件 -->
	<context:property-placeholder location="classpath:mysql.properties" />
	<!-- 第3步配置数据库连接池:C3P0,DBCP2,DRUID,这里使用的是DBCP2 -->
	<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource"
		destroy-method="close">
		<!--配置数据库的驱动,url,用户名和密码-->
		<property name="driverClassName" value="${jdbc.driver}"></property>
		<property name="url" value="${jdbc.url}"></property>
		<property name="username" value="${jdbc.username}"></property>
		<property name="password" value="${jdbc.password}"></property>
		<!-- 自动提交 -->
		<property name="defaultAutoCommit" value="false"></property>
		<!--  只读-->
		<property name="defaultReadOnly" value="false"></property>
		<!-- 隔离级别:8 可串行化 4可重复读 2读已提交 1 读未提交 -->
		<property name="defaultTransactionIsolation" value="4"></property>
		<!-- 连接池初始化连接数 -->
		<property name="initialSize" value="20"></property>
		<!-- 最大连接数 -->
		<property name="maxTotal" value="50"></property>
		<!-- 空闲区最大连接数和最小连接数 -->
		<property name="maxIdle" value="20"></property>
		<property name="minIdle" value="0"></property>
		<!-- 默认的查询超时时间5s -->
		<property name="defaultQueryTimeout" value="5"></property>
		<!-- 设置数据库校验查询语句 -->
		<property name="validationQuery" value="select now() from dual"></property>
		<!--连接创建或借出时,确保连接是否可用 -->
		<property name="testOnCreate" value="true"></property>
		<property name="testOnBorrow" value="true"></property>
		<!-- 校验查询语句超时时间5s -->
		<property name="validationQueryTimeout" value="5"></property>
		<!--连接池允许存放SQL预编译对象 -->
		<property name="poolPreparedStatements" value="true"></property>
		<!-- 最多可存放的SQL预编译对象 -->
		<property name="maxOpenPreparedStatements" value="120"></property>
	</bean>
	<bean id="sessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="dataSource"></property>
		<!-- typeAliasesPackage 以包为单位,批量给包中的类取类别名 如果存在多个包同时需要取类别名,包和包之间,采用;或者,间隔 -->
		<property name="typeAliasesPackage" value="com.gezhi.smspring.bean"></property>
	</bean>
	<!-- 第5步,配置MapperScanner -->
	<bean id="mapperScanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
		<property name="basePackage"
			value="com.gezhi.smspring.usermag.mapper;com.gezhi.smspring.logmag.mapper"></property>
		<property name="sqlSessionFactoryBeanName" value="sessionFactory"></property>
	</bean>
	<!-- 第6步,配置事务管理器 -->
	<bean id="transactionManager"
		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"></property>
	</bean>

	<!-- 第7步,配置spring管理事务的2中方式:编程式事务管理,声明式事务管理 -->
	<tx:advice id="txAdvice" transaction-manager="transactionManager">
		<tx:attributes>
		//SUPPORTS
			<tx:method name="*" read-only="true" propagation="SUPPORTS" />
			<tx:method name="save*" read-only="false" rollback-for="java.lang.Exception"
				propagation="REQUIRED" />
			<tx:method name="add*" read-only="false" rollback-for="java.lang.Exception"
				propagation="REQUIRED" />
			<tx:method name="insert*" read-only="false" rollback-for="java.lang.Exception"
				propagation="REQUIRED" />
			<tx:method name="create*" read-only="false" rollback-for="java.lang.Exception"
				propagation="REQUIRED" />
			<tx:method name="update*" read-only="false" rollback-for="java.lang.Exception"
				propagation="REQUIRED" />
			<tx:method name="modify*" read-only="false" rollback-for="java.lang.Exception"
				propagation="REQUIRED" />
			<tx:method name="change*" read-only="false" rollback-for="java.lang.Exception"
				propagation="REQUIRED" />
			<tx:method name="delete*" read-only="false" rollback-for="java.lang.Exception"
				propagation="REQUIRED" />
			<tx:method name="del*" read-only="false" rollback-for="java.lang.Exception"
				propagation="REQUIRED" />
			<tx:method name="remove*" read-only="false" rollback-for="java.lang.Exception"
				propagation="REQUIRED" />
		</tx:attributes>

	</tx:advice>
	<!-- 开启切面动态代理 -->
	<aop:aspectj-autoproxy></aop:aspectj-autoproxy>


</beans>

pom.xml

<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.gezhi</groupId>
	<artifactId>smspring</artifactId>
	<version>1.0</version>
	<packaging>jar</packaging>

	<name>smspring</name>
	<url>http://maven.apache.org</url>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<junit.version>4.12</junit.version>
		<log4j.version>1.2.17</log4j.version>
		<mybatis.version>3.3.0</mybatis.version>
		<mysql.version>5.1.38</mysql.version>
		<spring.version>4.3.14.RELEASE</spring.version>
		<aspect.version>1.8.9</aspect.version>
		<dbcp.version>2.4.0</dbcp.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-dbcp2</artifactId>
			<version>${dbcp.version}</version>
		</dependency>
		<!-- 导入spring容器相关JAR文件 -->
		<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>

		<!-- 引入spring框架兼容Junit单元测试框架的相关JAR包 -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-test</artifactId>
			<version>${spring.version}</version>
			<scope>test</scope>
		</dependency>
		<!-- 引入spring框架兼容mybatis持久层框架JAR包 -->
		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis-spring</artifactId>
			<version>1.3.2</version>
		</dependency>
		<!-- 引入Junit单元测试框架的相关JAR包 -->
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>${junit.version}</version>
			<scope>test</scope>
		</dependency>
		<!--引入日志JAR包 -->
		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>${log4j.version}</version>
		</dependency>
		<!-- 持久层框架mybatisJAR包 -->
		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis</artifactId>
			<version>${mybatis.version}</version>
		</dependency>
		<!-- mysql数据库JAR包 -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>${mysql.version}</version>
		</dependency>
		<!-- 引入第三方切面相关JAR包 -->
		<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjrt</artifactId>
			<version>${aspect.version}</version>
		</dependency>
		<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjweaver</artifactId>
			<version>${aspect.version}</version>
		</dependency>
	</dependencies>
	<build>
		<pluginManagement>
			<!-- 配置maven 在构建项目时,采用相关插件 -->
			<plugins>
				<plugin>
					<groupId>org.apache.maven.plugins</groupId>
					<artifactId>maven-compiler-plugin</artifactId>
					<version>3.8.0</version>
					<configuration>
						<source>1.8</source>
						<target>1.8</target>
					</configuration>
				</plugin>
			</plugins>
		</pluginManagement>
	</build>
</project>

JAR包一览

Spring和mybatis整合

包组织结构图

Spring和mybatis整合