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>