1、导入相关jar包:
junit、mybatis、mysql数据库、Spring相关、AOP织入、mybatis-spring包【新的包】、Spring操作数据库需要一个Spring-jdbc的包;
<dependencies>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.16</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjrt -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>
</dependencies>
mybatis-spring包的官网:
http://mybatis.org/spring/zh/index.html
;
后面学习SpringBoot框架的时候:引入mybatis/spring-boot-starter包,官网地址为:https://github.com/mybatis/spring-boot-starter
;
【注意】:
jar包搭配的时候,遵循官网的建议:
2、回忆MyBatis:
(1)编写实体类
@Data
public class Stu {
private String sid;
private String sname;
private Integer age;
private String gender;
编写get和set访问器……
}
(2)编写核心配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<!--configuration核心配置文件-->
<configuration>
<properties resource="db.properties"></properties>
<typeAliases>
<package name="org.westos.pojo"/>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${db.driver}"/>
<property name="url" value="${db.url}"/>
<property name="username" value="${db.username}"/>
<property name="password" value="${db.password}"/>
</dataSource>
</environment>
</environments>
<!--加载mapper映射文件-->
<mappers>
<package name="org.westos.mapper"/>
</mappers>
</configuration>
----用到的db.properties
db.driver=com.mysql.cj.jdbc.Driver
db.url=jdbc:mysql://127.0.0.1:3306/enducation?serverTimezone=UTC&characterEncoding=utf-8
db.username=root
db.password=123456
(3)编写接口
public interface StuMapper {
public List<Stu> selectStu();
}
(4)编写mapper.xml
<mapper namespace="org.westos.mapper.StuMapper">
<select id="selectStu" resultType="Stu">
select * from stu
select>
mapper>
(5)测试
@Test
public void test() throws IOException {
String resources = "mybatis-config.xml";
InputStream stream = Resources.getResourceAsStream(resources);
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(stream);
SqlSession sqlSession = sessionFactory.openSession(true);
StuMapper mapper = sqlSession.getMapper(StuMapper.class);
List<Stu> list = mapper.selectStu();
for (Stu stu : list) {
System.out.println(JSON.toJSONString(stu, true));
}
sqlSession.close();
}
创建mapper接口:
public interface StuMapper {
public List<Stu> selectStu();
}
创建mapper.xml配置文件:
<mapper namespace="org.westos.mapper.StuMapper">
<select id="selectStu" resultType="Stu">
select * from stu
select>
mapper>
编写mapper接口的实现类:
public class StuMapperImpl implements StuMapper {
//我们的所有操作都是用SqlSession来执行,现在都使用SqlSessionTemplate
private SqlSessionTemplate sqlSessionTemplate;
public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {
this.sqlSessionTemplate = sqlSessionTemplate;
}
public List<Stu> selectStu() {
StuMapper stuMapper = sqlSessionTemplate.getMapper(StuMapper.class);
return stuMapper.selectStu();
}
}
我们不再使用
SqlSession
对象,而是使用SqlSessionTemplate
对象代替它;
applicationContext.xml核心配置文件:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:p="http://www.springframework.org/schema/p"
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.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
<context:annotation-config/>
<context:component-scan base-package="org.westos"/>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="username" value="root"/>
<property name="password" value="123456"/>
<property name="url"
value="jdbc:mysql://127.0.0.1:3306/enducation?serverTimezone=UTC&characterEncoding=utf-8"/>
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="classpath:mybatis-config.xml"/>
bean>
<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory"/>
bean>
<bean id="stuMapper" class="org.westos.mapper.StuMapperImpl">
<property name="sqlSessionTemplate" ref="sqlSessionTemplate"/>
bean>
beans>
测试:
@Test
public void test1(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
StuMapper stuMapper = (StuMapper) context.getBean("stuMapper");
List<Stu> list = stuMapper.selectStu();
for (Stu stu : list) {
System.out.println(stu);
}
}
现在这个环境中,MyBatis就彻底不见了,整个代码非常的简洁;
SqlSessionTemplate
是 MyBatis-Spring 的核心。作为 SqlSession
的一个实现,这意味着可以使用它无缝代替你代码中已经在使用的 SqlSession。SqlSessionTemplate
是线程安全的,可以被多个 DAO 或映射器所共享使用。SqlSessionTemplate
将会保证使用的 SqlSession
与当前 Spring 的事务相关。 此外,它管理 session 的生命周期,包含必要的关闭、提交或回滚操作。另外,它也负责将 MyBatis 的异常翻译成 Spring 中的 DataAccessExceptions
。SqlSessionDaoSupport
是一个抽象的支持类,用来为你提供 SqlSession。调用 getSqlSession()
方法你会得到一个 SqlSessionTemplate
,之后可以用于执行 SQL 方法;首先,创建一个Mapper接口的实现类,该类继承了SqlSessionDaoSupport类:
public class StuMapperImpl2 extends SqlSessionDaoSupport implements StuMapper {
public List<Stu> selectStu() {
SqlSession sqlSession = getSqlSession();
return sqlSession.getMapper(StuMapper.class).selectStu();
}
}
编写核心配置文件:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="username" value="root"/>
<property name="password" value="123456"/>
<property name="url"
value="jdbc:mysql://127.0.0.1:3306/enducation?serverTimezone=UTC&characterEncoding=utf-8"/>
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="classpath:mybatis-config.xml"/>
bean>
<bean id="stuMapper2" class="org.westos.mapper.StuMapperImpl2">
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
bean>
beans>
可以看到,使用这个方式,比前者更简单,不需要创建sqlSessionTemplate
对象,直接给mapper接口的实现类注入sqlSessionFactory
对象即可;而且对事务的支持更加友好 . 可跟踪源码查看;
除了这些方式可以实现整合之外,我们还可以使用注解来实现;
更详细的介绍在我的另一篇文章中,点击这里跳转;
原子性
一致性
隔离性:多个业务能操作同一个资源,防止数据损坏;
持久性:事务一旦提交,无论系统发生什么问题,结果都不会再被影响,被持久化的写入存储器中;
创建Mapper接口文件:
public interface StudentMapper {
public List<Stu> selectStu();
//添加用户
public int addStu(Stu stu);
//删除用户
public int deleteStu(String id);
}
编写mapper配置文件:
<mapper namespace="org.westos.mapper.StudentMapper">
<select id="selectStu" resultType="Stu">
select * from stu
select>
<insert id="addStu" parameterType="Stu">
insert into stu(sid,sname,age,gender)
values(#{sid},#{sname},#{age},#{gender})
insert>
<delete id="deleteStu" parameterType="java.lang.String">
deletes from stu where id=#{id}
delete>
mapper>
定义Mapper接口的实现类:
public class StuMapperImpl extends SqlSessionDaoSupport implements StudentMapper {
public List<Stu> selectStu() {
Stu stu = new Stu("00001","张小小", 20, "male");
StudentMapper stuMapper = getSqlSession().getMapper(StudentMapper.class);
addStu(stu);
deleteStu("00001");
return stuMapper.selectStu();
}
public int addStu(Stu stu) {
return getSqlSession().getMapper(StudentMapper.class).addStu(stu);
}
public int deleteStu(String id) {
return getSqlSession().getMapper(StudentMapper.class).deleteStu(id);
}
}
Spring核心文件内容:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="username" value="root"/>
<property name="password" value="123456"/>
<property name="url"
value="jdbc:mysql://127.0.0.1:3306/enducation?serverTimezone=UTC&characterEncoding=utf-8"/>
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="classpath:mybatis-config.xml"/>
bean>
<bean id="stuMapper" class="org.westos.mapper.StuMapperImpl">
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
bean>
beans>
测试:
@Test
public void test() throws IOException {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
StuMapperImpl stuMapper = (StuMapperImpl) context.getBean("stuMapper");
List<Stu> list = stuMapper.selectStu();
for (Stu stu : list) {
System.out.println(stu);
}
}
结果:
报错:sql异常,delete写错了;但是插入数据成功!这是因为没有进行事务的管理。我们想让添加人和删除人都成功,有一个失败,就都失败,这时候就需要用都事务。
使用 MyBatis-Spring
的其中一个主要原因是它允许 MyBatis 参与到 Spring 的事务管理中,而不是给 MyBatis 创建一个新的专用事务管理器,MyBatis-Spring 借助了 Spring 中的 DataSourceTransactionManager
来实现事务管理。
一旦配置好了 Spring 的事务管理器,你就可以在 Spring 中按你平时的方式来配置事务。并且支持 @Transactional 注解
和 AOP 风格的配置。在事务处理期间,一个单独的 SqlSession
对象将会被创建和使用。当事务完成时,这个 session
会以合适的方式提交或回滚。
事务配置好了以后,MyBatis-Spring 将会透明地管理事务,这样在你的 DAO 类中就不需要额外的代码了。
Spring的事务管理分为两种:
编程式事务管理
将事务管理代码嵌到业务方法中来控制事务的提交和回滚
【缺点】:必须在每个事务操作业务逻辑中包含额外的事务管理代码;
声明式事务管理
一般情况下比编程式事务好用。
将事务管理代码从业务方法中分离出来,以声明的方式来实现事务管理。
将事务管理作为横切关注点,通过aop方法模块化。Spring中通过Spring AOP框架支持声明式事务管理。
标准配置
1、使用Spring管理事务,注意头文件的约束导入 : tx
xmlns:tx="http://www.springframework.org/schema/tx"
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
2、事务管理器
JDBC事务
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
bean>
3、配置好事务管理器后我们需要去配置事务的通知
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="add" propagation="REQUIRED"/>
<tx:method name="delete" propagation="REQUIRED"/>
<tx:method name="update" propagation="REQUIRED"/>
<tx:method name="search*" propagation="REQUIRED"/>
<tx:method name="get" read-only="true"/>
<tx:method name="*" propagation="REQUIRED"/>
tx:attributes>
tx:advice>
spring事务传播特性:
propagation_requierd:如果当前没有事务,就新建一个事务,如果已存在一个事务中,加入到这个事务中,这是最常见的选择。
propagation_supports:支持当前事务,如果没有当前事务,就以非事务方法执行。
propagation_mandatory:使用当前事务,如果没有当前事务,就抛出异常。
propagation_required_new:新建事务,如果当前存在事务,把当前事务挂起。
propagation_not_supported:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
propagation_never:以非事务方式执行操作,如果当前事务存在则抛出异常。
propagation_nested:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与
propagation_required类似的操作
PROPAGATION_REQUIRED
,它适合于绝大多数的情况。4、配置AOP:导入aop的头文件!
<aop:config>
<aop:pointcut id="txPointCut" expression="execution(* org.westos.mapper.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
aop:config>
5、进行测试
@Test
public void test() throws IOException {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
StuMapperImpl stuMapper = (StuMapperImpl) context.getBean("stuMapper");
List<Stu> list = stuMapper.selectStu();
for (Stu stu : list) {
System.out.println(stu);
}
}
如果不配置,就需要我们手动提交控制事务;事务在项目开发过程非常重要,涉及到数据的一致性的问题,不容马虎!