Spring整合MyBatis

Spring整合任何第三方资源套路基本一致。
Spring是一个对象容器

  1. 将第三方资源需要的对象注册在Spring容器中
  2. 将第三方资源的资源文件,交给Spring管理
  3. 所有第三方资源需要的内容全部从Spring中获取

整合MyBatis应该交给Spring的对象是?
SqlSessionFactoryBuilder(临时对象),
SqlSessionFactory(单例),
SqlSession,Mapper

整合

添加依赖

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.3.15</version>
    </dependency>
        <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>5.2.9.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.46</version>
    </dependency>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.6</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.13</version>
        <scope>test</scope>
    </dependency>
</dependencies>

添加一个中间依赖

    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis-spring</artifactId>
        <version>2.0.4</version>
    </dependency>

将数据源交给Spring管理,德鲁伊连接池,所谓配置连接池,就是配置一个数据源对象

添加druid的依赖

    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.1.10</version>
    </dependency>

在spring的配置文件中,解注册一个Druid的数据源
配置文件:

<!--引入外部资源文件-->
<context:property-placeholder location="classpath:config/db.properties"/>
<!--配置一个数据源-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <!--注入属性-->
        <property name="driverClassName" value="${druid.driver}"/>
        <property name="url" value="${druid.url}"/>
        <property name="username" value="${druid.username}"/>
        <property name="password" value="${druid.password}"/>

        <property name="initialSize" value="5"/>
        <property name="maxActive" value="15"/>
    </bean>

或者利用注解配置:

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

import javax.sql.DataSource;

@Configuration
@PropertySource(value = "config/db.properties")
public class DataSourceConfig {
    @Bean
    public DataSource dataSource(){
        return new DruidDataSource();
    }
}

其中配置文件resource/config/db.properties格式如下:

druid.url=jdbc:mysql://ip:3306/test?useUnicode=true&characterEncoding=UTF-8
druid.driver=com.mysql.jdbc.Driver
druid.username=username
druid.password=password

将SqlSessionFactory交给Spring管理
将MyBatis完全托管给Spring,所以MyBatis配置文件中的所有内容全部删除,只留根节点:

<?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>

在Spring的配置文件中注册一个SqlSessionFactory

    <!--注册SqlSessionFactory-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!--注入数据源-->
        <property name="dataSource" ref="dataSource"/>
        <!--settings 别名,映射文件注册-->
        <property name="typeAliasesPackage" value="org.example.entity"/>
        <!--注册映射文件,配置mapper文件所在位置-->
        <property name="mapperLocations" value="mapping/UserMapper.xml"/>
    </bean>

测试类

    @Test
    public void test(){
        ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
        SqlSessionFactory sqlSessionFactory=ac.getBean(SqlSessionFactory.class);
        SqlSession sqlSession=sqlSessionFactory.openSession();
        List<Object> objects=sqlSession.selectList("org.example.repository.UserRepository.findAll");
        System.out.println(objects);
    }

代理mapper的配置
MyBatis可以根据接口生成代理Mapper,Spring整合MyBatis之后一样可以生成代理Mapper,

定义Mapper接口

public interface UserRepository {
    public List<User> findAll();
}

给这个Mapper接口接口写一个对应的配置文件
配置文件中的namespace必须和Mapper接口的全限定类名一致,将配置文件与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="org.example.repository.UserRepository">

    <select id="findAll" resultType="org.example.entity.User">
        select * from t_user
    </select>
</mapper>

修改SqlSessionFactory中的映射文件的配置内容

    <!--注册SqlSessionFactory-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!--注入数据源-->
        <property name="dataSource" ref="dataSource"/>
        <!--settings 别名,映射文件注册-->
        <property name="typeAliasesPackage" value="org.example.entity"/>
        <!--注册映射文件,配置mapper文件所在位置-->
<!--        <property name="mapperLocations" value="mapping/UserMapper.xml"/>-->
    </bean>
    <!--配置一个自动扫描的映射类-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!--注入sqlSessionFactory的BeanName-->
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
        <!--注入mapper映射文件和接口所在的包名-->
        <property name="basePackage" value="org.example.repository"/>
    </bean>

测试类

    @Test
    public void test(){
        ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
        //从容器中获取对应的Mapper接口对象
        UserRepository userRepository=ac.getBean(UserRepository.class);
        List<User> users=userRepository.findAll();
        System.out.println(users);
    }

代理Mapper注意的几个细节

  1. mapper接口和mapper映射文件在一个包
  2. namespace必须和mapper接口的全限定类名
  3. mapper接口中的每个方法在mapper映射文件中都必须有对应的sql语句,sql语句的id必须和mapper接口中方法名一致

maven生成的执行文件中没有对应的映射文件会报错,原因是maven的工程结构中默认所有的资源文件(.properties,xml,ymal)等都是在src/main/resources下,所以当资源文件存在于src/main/java下时,maven不会将这些文件打包到输出目录中

调整方法:在pom.xml中加入

    <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*</include>
                </includes>
            </resource>
        </resources>
    </build>

注解方式配置

添加一个著配置类 AppConfig

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("org.example")
@MapperScan("org.example.repository")//配置映射文件和接口所在的包
public class AppConfig {
}

DataSource和SqlSessionFactory

import com.alibaba.druid.pool.DruidDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

import javax.sql.DataSource;

@Configuration
@PropertySource(value = "config/db.properties")
public class DataSourceConfig {
    @Value("${druid.username}")
    private String username;
    @Value("${druid.password}")
    private String password;
    @Value("${druid.url}")
    private String url;
    @Value("${druid.driver}")
    private String driverClassName;
    @Bean
    public DataSource dataSource(){
        DruidDataSource dataSource=new DruidDataSource();
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        dataSource.setUrl(url);
        dataSource.setDriverClassName(driverClassName);
        return dataSource;
    }
    @Bean
    public SqlSessionFactory sqlSessionFactory() throws Exception{
        SqlSessionFactoryBean sqlSessionFactoryBean=new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource());
        sqlSessionFactoryBean.setTypeHandlersPackage("org.example.entity");
        return sqlSessionFactoryBean.getObject();
    }
}

测试类

    @Test
    public void test(){
        ApplicationContext ac=new AnnotationConfigApplicationContext(AppConfig.class);
        UserRepository userRepository=ac.getBean(UserRepository.class);
        System.out.println(userRepository.findAll());
    }
12-08 08:59