3. Spring整合Mybatis编程DAO层开发
1. 项目引入相关依赖spring mybatis mysql mybatis-spring druid2. 编写spring.xml整合:spring 接管 mybatis 中 SqlSessionFactory对象的创建<!--创建DataSource--><bean class="com.alibaba.druid.pool.DruidDataSource" id="dataSource"><property name="driverClassName" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/lb"/><property name="username" value="root"/><property name="password" value="root"/></bean><!--创建sqlSessionFactory--><bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sqlSessionFactory"><!--依赖数据源--><property name="dataSource" ref="dataSource"/></bean>3. 建表4. 实体类5. DAO接口public interface UserDAO {List<User> findAll();}6. 开发Mapper<mapper namespace="com.baizhi.dao.UserDAO"><select id="findAdd" resultType="com.baizhi.eneity.User">select id, name, age, bir from t_user</select></mapper>注意:开发完mapper文件后一定要在spring.xml中注册<!--创建sqlSessionFactory--><bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sqlSessionFactory"><!--依赖数据源--><property name="dataSource" ref="dataSource"/><!--注册mapper配置文件--><property name="mapperLocations"><array><value>classpath:com/baizhi/mapper/UserDAOMapper.xml</value></array></property></bean>7. 启动工厂获取SqlSessionFactoryApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");SqlSessionFactory sqlSessionFactory = (SqlSessionFactory) context.getBean("sqlSessionFactory");SqlSession sqlSession = sqlSessionFactory.openSession();UserDAO userDAO = sqlSession.getMapper(UserDAO.class);userDAO.findAll().forEach(user -> {System.out.println(user);});再进一步可以直接在工厂中注册SqlSessionFactory、注册DAO组件类,并且在DAO组件里面注入SqlSessionFactory和DAO接口的类型,这样就可以使用spring工厂直接获取UserDAO组件类了不用再获取SqlSessionFactory了ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");UserDAO userDAO = (UserDAO) context.getBean("userDAO");
接下来我们来整合mybatis和spring并一步一步的开发DAO层:
首先,我们新建一个模块,使用标准的包结构
之后我们要在pom.xml文件中引入依赖
spring mybatis mysql mybatis-spring druid
<!--spring核心及相关依赖-->
<dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>4.3.2.RELEASE</version>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-beans</artifactId><version>4.3.2.RELEASE</version>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-web</artifactId><version>4.3.2.RELEASE</version>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-expression</artifactId><version>4.3.2.RELEASE</version>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-aop</artifactId><version>4.3.2.RELEASE</version>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>4.3.2.RELEASE</version>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-context-support</artifactId><version>4.3.2.RELEASE</version>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId><version>4.3.2.RELEASE</version>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>4.3.2.RELEASE</version>
</dependency><!--mysql-->
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.38</version>
</dependency><!--mybatis-->
<dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.4</version>
</dependency><!--mybatis-spring-->
<dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>2.0.4</version>
</dependency><!--druid-->
<dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.19</version>
</dependency>
在数据库中建表
创建实体类
public class User {private String id;private String name;private Integer age;private Date bir;public User() {}public User(String id, String name, Integer age, Date bir) {this.id = id;this.name = name;this.age = age;this.bir = bir;}// 成员变量的set、get方法以及类的to_String方法在博客中没有,是为了避免占用太多篇幅,但是这里其实是有的// 大家写的时候一定要写上
}
创建DAO接口
public interface UserDAO {List<User> findAll();
}
写Mapper配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.baizhi.dao.UserDAO"><!--查询表中所有记录--><select id="findAll" resultType="com.baizhi.eneity.User">select id, name, age, bir from t_user</select></mapper>
编写spring.xml文件进行整合
<?xml version="1.0" encoding="UTF-8"?>
<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"><!--创建DataSource--><bean class="com.alibaba.druid.pool.DruidDataSource" id="dataSource"><property name="driverClassName" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/lb"/><property name="username" value="root"/><property name="password" value="root"/></bean><!--创建sqlSessionFactory--><bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sqlSessionFactory"><!--因为使用了mybatis官方的创建SqlSessionFactory对象的工具类,所以不能使用mybatis的主配置文件了,主配置文件最重要的是数据源+mapper,所以我们要在这里写上数据源和mapper配置--><!--依赖数据源--><property name="dataSource" ref="dataSource"/><!--注册mapper配置文件--><property name="mapperLocations"><array><value>classpath:com/baizhi/mapper/UserDAOMapper.xml</value></array></property></bean></beans>
测试和结果
最后我们来说一个优化
对于我们来说,我们不关心SqlSessionFactory如何获取SqlSession的,也不关心SqlSession如何获取获取DAO接口的,我们关心能否一步就获得想要的DAO接口呢,这是可以的,我们先在工厂中注册SqlSessionFactory对象,因为SqlSessionFactory可以获取SqlSession对象,然后传入DAO接口类型就获得了DAO接口对象;然后我们可以在工厂中创建一个DAO组件类,注入SqlSessionFactory对象和DAO接口类型就可以直接获得DAO对象了,这个类就是mybatis-spring包中的MapperFactoryBean类
配置文件
<!--创建DataSource-->
<bean class="com.alibaba.druid.pool.DruidDataSource" id="dataSource"><property name="driverClassName" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/lb"/><property name="username" value="root"/><property name="password" value="root"/>
</bean><!--创建sqlSessionFactory-->
<bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sqlSessionFactory"><!--因为使用了mybatis官方的创建SqlSessionFactory对象的工具类,所以不能使用mybatis的主配置文件了,主配置文件最重要的是数据源+mapper,所以我们要在这里写上数据源和mapper配置--><!--依赖数据源--><property name="dataSource" ref="dataSource"/><!--注册mapper配置文件--><property name="mapperLocations"><array><value>classpath:com/baizhi/mapper/UserDAOMapper.xml</value></array></property>
</bean><!--创建DAO组件类-->
<bean class="org.mybatis.spring.mapper.MapperFactoryBean" name="userDAO"><!--注入SqlSessionFactory--><property name="sqlSessionFactory" ref="sqlSessionFactory"/><!--注入创建的DAO接口的类型 注入接口的全限定名 包.接口名--><property name="mapperInterface" value="com.baizhi.dao.UserDAO"/>
</bean>
- 测试和结果
public class TestUserDAO {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");UserDAO userDAO = (UserDAO) context.getBean("userDAO");userDAO.findAll().forEach(user -> System.out.println("user = " + user));}
}
总结:
4. Spring整合Mybatis编程Service层开发
# spring、mybatis整合Service层开发时如何加入事务控制1. Mybatis框架中事务控制SqlSession 提交:sqlSession.commit(); 回滚:sqlSession.rollback()// 无论用的是哪个简化数据库的框架,它的底层一定是jdbc,sqlSession底层调的也是Connection的commit()、rollback()Mybatis 是对 原始jdbc技术的封装 ===> Connection(数据库其实只认java.sql.Connection commit() | rollback())项目中真正负责数据库事务控制的对象:Connection 对象2. 用来实现事务控制的核心对象是Connection 连接对象的 commit() rollback()3. 如何在现有的项目中获取Connection对象注意:在现有项目中DruidDataSource是一个连接池 在连接池里面装的就是一个一个的Connection连接Connection conn = DruidDataSource.getConnection();4. 给现有业务层加入事务UserServiceImplprivate DataSource dataSource; // 提供公开的set方法save(){try{// 控制事务druidDataSource.getConnection().setAutoCommit(false) // 将事务提交方式改为手动// 处理业务// 调用DAOdruidDataSource.getConnection().commit();}catch(...){druidDataSource.getConnection().rollback();}}连接控制事务得保证是同一个连接对象,在业务层拿到的连接对象得和DAO真正执行时打开的数据库连接对象保持一致DAO真正执行是由框架内部的jar包创建出来的,不受控制,与业务层拿到的连接不是同一个,所以利用上面的代码控制事务是不行的4. 在Spring和Mybatis框架中提供了一个类DataSourceTransactionManager 数据源事务管理器作用1. 在全局创建一个事务管理器,用来统一调度 业务层当前线程使用的连接对象和DAO层使用的连接对象一致由它来决定哪个线程在执行业务层时用的是这个连接,在执行DAO时同样用这个连接创建<!--数据源管理器--><!--它是用来控制数据源的线程安全问题,它不生产数据源,所以要告诉它控制哪个数据源的线程安全问题,所以要注入数据源--><bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager"><!--注入数据源对象--><property name="dataSource" ref="dataSource"/></bean> 5. 给现有的业务层加入事务控制public class UserServiceImpl implements UserService{private UserDAO userDAO;private PlatformTransactionManager transactionManager; //setTransactionManager方法public void setUserDAO(UserDAO userDAO) {this.userDAO = userDAO;}@Overridepublic void save(User user) {try{// 创建事务配置对象// 接口,后面new的用实现类TransactionDefinition transactionDefinition = new DefaultTransactionDefinition();// 获取事务状态//传入事务配置TransactionStatus status = platformTransactionManager.getTransaction(transactionDefinition);//try {// 控制事务// 处理业务userDAO.save(user);int i = 1 / 0;// 需要传入事务状态platformTransactionManager.commit(status);} catch (Exception e) {e.printStackTrace();platformTransactionManager.rollback(status);}}
}
在具体讲解Spring整合Mybatis编程Service层开发之前,我们先来补充一个小的知识点
<!--一次性创建项目中所有DAO对象 MapperScannerConfigurerMapperScannerConfigurer:默认创建对象在工厂中唯一标识:接口的首字母小写的名字UserDAO=====> userDAO Userdao====> userdaoOrderDAO====> orderDAO Orderdao====> orderdaoEmpDAO====> empDAO
-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"><!--注入SqlSessionFactory--><property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/><!--扫描DAO接口所在的包--><property name="basePackage" value="com.baizhi.dao"/>
</bean>
- 使用MapperScannerConfigurer,一次性创建包中所有的接口
<!--创建sqlSessionFactory-->
<bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sqlSessionFactory"><!--因为使用了mybatis官方的创建SqlSessionFactory对象的工具类,所以不能使用mybatis的主配置文件了,主配置文件最重要的是数据源+mapper,所以我们要在这里写上数据源和mapper配置--><!--依赖数据源--><property name="dataSource" ref="dataSource"/><!--注册mapper配置文件--><property name="mapperLocations"><array><value>classpath:com/baizhi/mapper/UserDAOMapper.xml</value></array></property><!--注入别名相关配置 typeAliasesPackage:用来给指定包中所有类起别名 默认的别名:类名|类名首字母小写--><property name="typeAliasesPackage" value="com.baizhi.eneity"/>
</bean>
- typeAliasesPackage:用来给指定包中所有类起别名 默认的别名:类名|类名首字母小写
之后我们正式进入Spring整合Mybatis编程Service层开发
因为在前面开发DAO层时已经在pom.xml中导入依赖了,所以在开发Service时就不需要再导入依赖了,我们直接开发Service接口
public interface UserService {List<User> findAll();void save(User user);
}
这里我们先不管事务操作,创建UserService接口的实现类,UserService的实现类里面有一个userDAO接口对象
package com.baizhi.service;import com.baizhi.dao.UserDAO;
import com.baizhi.eneity.User;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;import java.util.List;
import java.util.UUID;public class UserServiceImpl implements UserService{private UserDAO userDAO;public void setUserDAO(UserDAO userDAO) {this.userDAO = userDAO;}@Overridepublic List<User> findAll() {// 查询操作不需要事务控制// 调用userDAO的方法return userDAO.findAll();}@Overridepublic void save(User user) {// 控制事务// 处理业务// 调用DAO// userDAO 方法上有一个小事务,仅限于DAO的方法,DAO的方法结束后会做一个提交,这个小事务仅是为了方便测试DAO// 当外部(Service方法内)存在事务时,小事务(仅限于DAO的方法中的事务)自动消失(小事务不生效)// // 调用userDAO的方法userDAO.save(user);//int i = 1 / 0;}
}
编写spring.xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<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"><!--创建DataSource--><bean class="com.alibaba.druid.pool.DruidDataSource" id="dataSource"><property name="driverClassName" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/lb"/><property name="username" value="root"/><property name="password" value="root"/></bean><!--创建sqlSessionFactory--><bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sqlSessionFactory"><!--因为使用了mybatis官方的创建SqlSessionFactory对象的工具类,所以不能使用mybatis的主配置文件了,主配置文件最重要的是数据源+mapper,所以我们要在这里写上数据源和mapper配置--><!--依赖数据源--><property name="dataSource" ref="dataSource"/><!--注册mapper配置文件--><property name="mapperLocations"><array><value>classpath:com/baizhi/mapper/UserDAOMapper.xml</value></array></property><!--注入别名相关配置 typeAliasesPackage:用来给指定包中所有类起别名 默认的别名:类名|类名首字母小写--><property name="typeAliasesPackage" value="com.baizhi.eneity"/></bean><!--一次性创建项目中所有DAO对象 MapperScannerConfigurerMapperScannerConfigurer:默认创建对象在工厂中唯一标识:接口的首字母小写的名字UserDAO=====> userDAO Userdao====> userdaoOrderDAO====> orderDAO Orderdao====> orderdaoEmpDAO====> empDAO--><bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"><!--注入SqlSessionFactory--><property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/><!--扫描DAO接口所在的包--><property name="basePackage" value="com.baizhi.dao"/></bean><!--管理Service组件--><bean class="com.baizhi.service.UserServiceImpl" name="userService"><property name="userDAO" ref="userDAO"/></bean></beans>
测试和结果
测试之前t_user表中记录:
运行代码:
运行之后t_user表中记录:
上面表记录说明执行成功了。
接下来我们尝试使用事务进行管理
我们先看一下是否有事务自动提交
为什么有异常却仍然插入了数据呢,这时因为userDAO 方法上有一个小事务,仅限于DAO的方法,DAO的方法结束后会做一个提交,这个小事务仅是为了方便测试DAO, 当外部(Service方法内)存在事务时,小事务(仅限于DAO的方法中的事务)自动消失(小事务不生效)。所以我们就需要手动进行管理了,我们知道,无论什么框架与数据库打交道时,底层都是Connection对象与数据库打交道,所以我们尝试用Connection进行事务管理,但是这确实不行的,因为Connection管理事务的前提是相同的Connection对象,当调用userDAO管理事务的Connection对象和userService管理事务的Connection对象不是同一个,那怎么办呢?官方提供了事务管理器类platformTransactionManager,它是用来控制数据源的线程安全问题,它不生产数据源,我们把它声明为成员变量,并声明公开的set方法,让spring工厂管理,所以UserServiceImpl实现类代码如下:
UserServiceImpl实现类
public class UserServiceImpl implements UserService{private UserDAO userDAO;// 声明事务管理器// PlatformTransactionManager是一个接口// DataSourceTransactionManager是PlatformTransactionManage的子类private PlatformTransactionManager platformTransactionManager;public void setPlatformTransactionManager(PlatformTransactionManager platformTransactionManager) {this.platformTransactionManager = platformTransactionManager;}public void setUserDAO(UserDAO userDAO) {this.userDAO = userDAO;}@Overridepublic List<User> findAll() {// 查询操作不需要事务控制return userDAO.findAll();}@Overridepublic void save(User user) {// 创建事务配置对象// 接口,后面new的用实现类TransactionDefinition transactionDefinition = new DefaultTransactionDefinition();// 获取事务状态//创建事务配置TransactionStatus status = platformTransactionManager.getTransaction(transactionDefinition);//try {// 控制事务// 处理业务// 调用DAO// userDAO 方法上有一个小事务,仅限于DAO的方法,DAO的方法结束后会做一个提交,这个小事务仅是为了方便测试DAO// 当外部(Service方法内)存在事务时,小事务(仅限于DAO的方法中的事务)自动消失(小事务不生效)userDAO.save(user);int i = 1 / 0;// 需要传入事务状态platformTransactionManager.commit(status);} catch (Exception e) {e.printStackTrace();platformTransactionManager.rollback(status);}}
}
mapper配置文件
<?xml version="1.0" encoding="UTF-8"?>
<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"><!--创建DataSource--><bean class="com.alibaba.druid.pool.DruidDataSource" id="dataSource"><property name="driverClassName" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/lb"/><property name="username" value="root"/><property name="password" value="root"/></bean><!--创建sqlSessionFactory--><bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sqlSessionFactory"><!--因为使用了mybatis官方的创建SqlSessionFactory对象的工具类,所以不能使用mybatis的主配置文件了,主配置文件最重要的是数据源+mapper,所以我们要在这里写上数据源和mapper配置--><!--依赖数据源--><property name="dataSource" ref="dataSource"/><!--注册mapper配置文件--><property name="mapperLocations"><array><value>classpath:com/baizhi/mapper/UserDAOMapper.xml</value></array></property><!--注入别名相关配置 typeAliasesPackage:用来给指定包中所有类起别名 默认的别名:类名|类名首字母小写--><property name="typeAliasesPackage" value="com.baizhi.eneity"/></bean><!--一次性创建项目中所有DAO对象 MapperScannerConfigurerMapperScannerConfigurer:默认创建对象在工厂中唯一标识:接口的首字母小写的名字UserDAO=====> userDAO Userdao====> userdaoOrderDAO====> orderDAO Orderdao====> orderdaoEmpDAO====> empDAO--><bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"><!--注入SqlSessionFactory--><property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/><!--扫描DAO接口所在的包--><property name="basePackage" value="com.baizhi.dao"/></bean><!--管理Service组件--><bean class="com.baizhi.service.UserServiceImpl" name="userService"><property name="userDAO" ref="userDAO"/><property name="platformTransactionManager" ref="transactionManager"/></bean><!--数据源管理器--><!--它是用来控制数据源的线程安全问题,它不生产数据源,所以要告诉它控制哪个数据源的线程安全问题,所以要注入数据源--><bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager"><!--注入数据源对象--><property name="dataSource" ref="dataSource"/></bean></beans>
测试和结果
测试之前的表
测试:
测试之后的表:
上述结果说明我们成功的使用事务管理了Service层。
总结:
————————————————
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/qq_50313418/article/details/123301769