(五)Spring-spring和mybatis的整合
一、整合要點
1.1 準備工作
spring和mybatis的官網整合地址為:
http://www.mybatis.cn/archives/769.html
需要導入依賴:
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.3</version>
</dependency>
1.2 數據源替換
spring配置文件的數據源替換mybatis配置文件的數據源
1 原mybatis-config.xml文件
<?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" >
<property name="" value=""/>
</properties>
<typeAliases>
<package name="com.happy.pojo"/>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
<environment id="uat">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<!-- 每一個mapper.xml都需要在mybatis核心配置文件中註冊-->
<!-- <mapper resource="org/mybatis/example/BlogMapper.xml"/>-->
<!-- <mapper resource="com/happy/dao/UserMapper.xml"></mapper>-->
<package name="com.happy.mapper.user"/>
</mappers>
</configuration>
2 用spring.xml替換為:
<context:property-placeholder location="db.properties"/>
<!--註冊一個datasource,使用spring的datasource替換mybatis的配置,c3p0,dbcp,druid-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${driver}"></property>
<property name="url" value="${url}"></property>
<property name="username" value="${username}"></property>
<property name="password" value="${password}"></property>
</bean>
1.3 sqlSessionFactory替換
1 原mybatis實現為工具類
原來mybatis框架需要代碼用工具類實現獲取SqlSessionFactory,主要是通過讀取原來mybatis的配置文件,獲取數據源信息,生成SqlSessionFactory對象
如下
package com.happy.utils;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
import java.sql.DriverManager;
public class MybatisUtils {
private static SqlSessionFactory sqlSessionFactory;
static {
try {
//使用mybatis第一步:獲取sqlSessionFactory對象
String resource = "mybatis-config.xml";
//InputStream inputStream = MybatisUtils.class.getClassLoader().getResourceAsStream(resource);
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//使用uat環境數據庫
//sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream,"uat");
} catch (IOException e) {
e.printStackTrace();
}
}
public static SqlSession getSqlSession() {
SqlSession sqlSession = sqlSessionFactory.openSession();
return sqlSession;
}
public static void release(SqlSession sqlSession){
}
}
2 用spring.xml替換為:
在 MyBatis-Spring 中,可使用 SqlSessionFactoryBean 來創建 SqlSessionFactory。 要配置這個工廠 Bean,只需要把下面代碼放在 Spring 的 XML 配置文件中:
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
</bean>
1.4 獲取Mapper方式替換
1 原mybatis實現為用工具類獲取MybatisUtils.getSqlSession()
之前為在service層,通過在方法類使用工具類分兩步獲取mapper:
- MybatisUtils.getSqlSession()獲取SqlSession,實際工具類為通過SqlSessionFactory獲取
- 然後通過getSqlSession獲取mapper
package com.happy.service.user.impl;
import com.happy.mapper.user.UserMapper;
import com.happy.pojo.User;
import com.happy.service.user.UserService;
import com.happy.utils.MybatisUtils;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.List;
public class UserServiceImpl implements UserService {
UserMapper userMapper;
@Override
public List<User> getUserList() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
userMapper = sqlSession.getMapper(UserMapper.class);
List<User> userList = userMapper.getUserList();
return userList;
}
@Override
public User getUserById(int id) {
SqlSession sqlSession = MybatisUtils.getSqlSession();
userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.getUserById(id);
return user;
}
@Test
public void test(){
List<User> userList = getUserList();
System.out.println(userList);
}
@Test
public void testGetUserById(){
User user = getUserById(3);
System.out.println(user);
}
}
2 用spring.xml配置mapper
<!--3.註冊一個MapperFactoryBean 用於獲取mapper-->
<!--需要關聯UserMapper 相當於原來的sqlSession.getMapper(UserMapper.class)-->
<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="com.happy.mapper.user.UserMapper" />
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
3 測試使用
用spring.xml配置mapper後,這樣獲取和使用:
package com.happy.service.user.impl;
import com.happy.mapper.user.UserMapper;
import com.happy.pojo.User;
import com.happy.service.user.UserService;
import com.happy.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserServiceImpl implements UserService {
@Autowired
@Qualifier("userMapper")
UserMapper userMapper;
@Override
public List<User> getUserList() {
List<User> userList = userMapper.getUserList();
return userList;
}
@Override
public User getUserById(int id) {
User user = userMapper.getUserById(id);
return user;
}
@Test
public void testGetUserList(){
ApplicationContext context = new ClassPathXmlApplicationContext("application-context.xml");
UserService userService = context.getBean("userServiceImpl", UserService.class);
List<User> userList =userService.getUserList();
for (User user : userList) {
System.out.println(user);
}
}
@Test
public void testGetUserById(){
ApplicationContext context = new ClassPathXmlApplicationContext("application-context.xml");
UserService userService = context.getBean("userServiceImpl", UserService.class);
User user = userService.getUserById(3);
System.out.println(user);
}
}
1.5 小結
一般,最終結合後的項目總結構如下:
1 一個總配置文件application-context.xml用來配置spring總的配置
- application-context.xml如下,負責開啓註解,包掃描等
- 注意import其他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"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<!--總配置-->
<!--導入其他組件配置-->
<import resource="spring-mybatis.xml"></import>
<!--<import resource="spring-mvc.xml"></import>-->
<!--開啓註解支持-->
<context:annotation-config></context:annotation-config>
<context:component-scan base-package="com.happy"></context:component-scan>
<aop:aspectj-autoproxy proxy-target-class="false"></aop:aspectj-autoproxy>
</beans>
2 總配置下導入其他組件配置(如spring-mybatis.xml,spring-mvc.xml)和業務bean(如spring-user.xml)
- spring-mybatis.xml如下,負責spring集成mybatis的所有配置,主要包括數據源和sqlSessionFactory
- 數據源可以引用外部properties文件。
- 註冊mapper,通過
MapperFactoryBean將接口加入到 Spring 中,需要注意的是:所指定的映射器類必須是一個接口,而不是具體的實現類。在這個示例中,通過註解來指定 SQL 語句,但是也可以使用 MyBatis 映射器的 XML 配置文件 - MapperFactoryBean
在這裏註冊mapper,實際為mapper接口的一個動態代理(已經注入了sqlSession等屬性) MapperFactoryBean將會負責SqlSession的創建和關閉。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<context:property-placeholder location="db.properties"/>
<!--註冊bean-->
<!--1.註冊一個datasource,使用spring的datasource替換mybatis的配置,c3p0,dbcp,druid-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<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>
</bean>
<!--2.註冊一個sqlSessionFactory 用於生成sqlSession-->
<!-- String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:Mybatis-config.xml"></property>
<!--<property name="mapperLocations" value="classpath:com/happy/mapper/user/UserMapper.xml"></property>-->
</bean>
<!--3.註冊一個MapperFactoryBean 用於獲取mapper-->
<!--需要關聯UserMapper接口 相當於原來的sqlSession.getMapper(UserMapper.class)-->
<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="com.happy.mapper.user.UserMapper" />
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
</beans>
3 mybatis-config.xml原生配置文件
- mybatis-config.xml,mybatis原生配置文件將數據源、sqlSessionFactory等去掉(已在spring中配置)
- 注意在spring中配置中配置sqlSessionFactory的時候引用mybatis配置文件
- mybatis原生配置文件,一般保留配置如下(也可以全部放到spring中配置):
- typeAliases
mappers,負責mybatis的beans.xml文件和mapper接口映射- settings配置
<?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>
<!--個人習慣在mybatis原生配置文件裏保存typeAliases,mappers,和settings配置-->
<!--其餘都放在spring裏配置-->
<typeAliases>
<package name="com.happy.pojo"/>
</typeAliases>
<mappers>
<!-- 每一個mapper.xml都需要在mybatis核心配置文件中註冊-->
<!-- <mapper resource="org/mybatis/example/BlogMapper.xml"/>-->
<!-- <mapper resource="com/happy/dao/UserMapper.xml"></mapper>-->
<package name="com.happy.mapper.user"/>
</mappers>
</configuration>
4 編寫mapper接口和mapper.xml文件
UserMapper.java
package com.happy.mapper.user;
import com.happy.pojo.User;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;
public interface UserMapper {
@Select("select * from user")
List<User> getUserList();
User getUserById(@Param("id") int id);
}
UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.happy.mapper.user.UserMapper">
<!-- <select id="getUserList" resultType="user">-->
<!-- select * from user;-->
<!-- </select>-->
<select id="getUserById" resultType="user">
select * from user where id=#{id};
</select>
</mapper>
5 service層調用mapper接口
- 可以使用spring.xml註冊service層的bean,也可以使用@Service註解等注入容器
- 註冊service的bean時,注意屬性注入依賴mapper
- 使用時,如controller直接從容器中獲取service的bean即可以實現業務。
- 配置好之後,你就可以像 Spring 中普通的 bean 注入方法那樣,將映射器注入到你的業務或服務對象中。
MapperFactoryBean將會負責SqlSession的創建和關閉。 如果使用了 Spring 的事務功能,那麼當事務完成時,session 將會被提交或回滾。最終任何異常都會被轉換成 Spring 的DataAccessException異常。
package com.happy.service.user.impl;
import com.happy.mapper.user.UserMapper;
import com.happy.pojo.User;
import com.happy.service.user.UserService;
import com.happy.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserServiceImpl implements UserService {
@Autowired
@Qualifier("userMapper")
UserMapper userMapper;
@Override
public List<User> getUserList() {
List<User> userList = userMapper.getUserList();
return userList;
}
@Override
public User getUserById(int id) {
User user = userMapper.getUserById(id);
return user;
}
@Test
public void testGetUserList(){
ApplicationContext context = new ClassPathXmlApplicationContext("application-context.xml");
UserService userService = context.getBean("userServiceImpl", UserService.class);
List<User> userList =userService.getUserList();
for (User user : userList) {
System.out.println(user);
}
}
@Test
public void testGetUserById(){
ApplicationContext context = new ClassPathXmlApplicationContext("application-context.xml");
UserService userService = context.getBean("userServiceImpl", UserService.class);
User user = userService.getUserById(3);
System.out.println(user);
}
}
二、整合方式二-使用 SqlSession
在 MyBatis 中,你可以使用 SqlSessionFactory 來創建 SqlSession。 一旦你獲得一個 session 之後,你可以使用它來執行映射了的語句,提交或回滾連接,最後,當不再需要它的時候,你可以關閉 session。 使用 MyBatis-Spring 之後,你不再需要直接使用 SqlSessionFactory 了,因為你的 bean 可以被注入一個線程安全的 SqlSession,它能基於 Spring 的事務配置來自動提交、回滾、關閉 session。第二種方式又包括以下兩種方式:
2.1 使用SqlSessionTemplate
SqlSessionTemplate 是 MyBatis-Spring 的核心。作為 SqlSession 的一個實現,這意味着可以使用它無縫代替你代碼中已經在使用的 SqlSession。 SqlSessionTemplate 是線程安全的,可以被多個 DAO 或映射器所共享使用。
當調用 SQL 方法時(包括由 getMapper() 方法返回的映射器中的方法),SqlSessionTemplate 將會保證使用的 SqlSession 與當前 Spring 的事務相關。 此外,它管理 session 的生命週期,包含必要的關閉、提交或回滾操作。另外,它也負責將 MyBatis 的異常翻譯成 Spring 中的 DataAccessExceptions。
由於模板可以參與到 Spring 的事務管理中,並且由於其是線程安全的,可以供多個映射器類使用,你應該總是用 SqlSessionTemplate 來替換 MyBatis 默認的 DefaultSqlSession 實現。在同一應用程序中的不同類之間混雜使用可能會引起數據一致性的問題。
可以使用 SqlSessionFactory 作為構造方法的參數來創建 SqlSessionTemplate 對象。
2.2 SqlSessionDaoSupport
SqlSessionDaoSupport 是一個抽象的支持類,用來為你提供 SqlSession。調用 getSqlSession() 方法你會得到一個 SqlSessionTemplate,之後可以用於執行 SQL 方法,就像下面這樣:
2.3 小結
- 詳細方法見官網:
http://mybatis.org/spring/zh/sqlsession.html# - 注入映射器(參照方式一),與其在數據訪問對象(DAO)中手工編寫使用
SqlSessionDaoSupport或SqlSessionTemplate的代碼,還不如讓 Mybatis-Spring 為你創建一個線程安全的映射器,這樣你就可以直接注入到其它的 bean 中了,如下面使用構造器注入,也可以使用屬性注入。
<bean id="fooService" class="org.mybatis.spring.sample.service.FooServiceImpl">
<constructor-arg ref="userMapper" />
</bean>