(五)Spring-spring和mybatis的整合

(五)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 的一个实现,这意味着可以使用它无缝代替你代码中已经在使用的 SqlSessionSqlSessionTemplate 是线程安全的,可以被多个 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)中手工编写使用 SqlSessionDaoSupportSqlSessionTemplate 的代码,还不如让 Mybatis-Spring 为你创建一个线程安全的映射器,这样你就可以直接注入到其它的 bean 中了,如下面使用构造器注入,也可以使用属性注入。

    <bean id="fooService" class="org.mybatis.spring.sample.service.FooServiceImpl">
      <constructor-arg ref="userMapper" />
    </bean>
    
posted @ 2022-05-10 18:30  高兴518  阅读(46)  评论(0编辑  收藏  举报