Mybatis整合Spring的原理以及整合一个案例

目录

一.Mybatis整合Spring的好处

注册会话工厂(SqlSessionFactory),不用手动创建

自动创建线程安全的会话,自动获取mapper接口的代理类并放入spring容器

二.依赖、配置与实现

1.加入相关依赖

2.编写配置文件

3.代码流程

总结:


一.Mybatis整合Spring的好处

Mybatis整合Spring给我们带来的好处

  • Spring可以帮我们管理对象
  • 简化方法的调用

Mybatis利用Spring的扩展点,把自己与Spring进行了整合

注册会话工厂(SqlSessionFactory),不用手动创建

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--        配置主配置文件地址-->
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
<!--        注册mapper.xml-->
        <property name="dataSource" ref="dataSource"/>
    </bean>

原理:

org.mybatis.spring.SqlSessionFactoryBean这个类实现了FactoryBean、InitializingBean、ApplicationListener

熟悉Spring流程的应该知道FactoryBean是Spring注册bean的一种特殊的方式,他的getObject方法可以自定义的创建对象,他会解析我们的Mybitis的配置文件,最终把SqlSessionFactoryBean注册到Spring的容器,然后我们getbean(SqlSessionFactoryBean)的时候就可以得到SqlSessionFactory对象

自动创建线程安全的会话,自动获取mapper接口的代理类并放入spring容器

DefaultSqlSession是线程不安全的,所以我们并不可以直接用DefaultSqlSession。
SqlSessionTemplete 是他的替代品,他采用jdk动态代理 每次创建一个新的DefSqlSession
 

<bean id="mapperScanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
    <!--指定包名, 包名是mapper接口所在的包名。
     MapperscannerConfigurer会扫描这个包中的所有接口,把每个接口都执行
     一次getMapper()方法 ,得到每个接口的代理对象。
     创建好的代理对象放入到spring的容器中的。-->
    <property name="basePackage" value="com.ws.mapper"/>
</bean>

原理:

org.mybatis.spring.mapper.MapperScannerConfigurer这个类实现了BeanDefinitionRegistryPostProcessor接口,他也是注册bean的一种方式,实现他的方法可以直接

注册beanDifinition.他会扫描我们注册的mapper接口,把扫描到的接口name注册成beanDefinition的beanNamesetBeanClass时,他传入了 MapperFactoryBean对象MapperFactoryBean是又实现了FactoryBean的类,他的getObject方法就是获取SqlSession,调用getMapper方法,所以Mybatis会帮他动态代理生成mapper接口的代理对象。

所以就不用我们手动的创建SqlSession,也不用手动调用getMapper.

他会先获取SqlSessionTemplete

二.依赖、配置与实现

1.加入相关依赖

<dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
<!-- spring依赖-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.2.8.RELEASE</version>
    </dependency>

<!--    Mybitis依赖-->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.5.1</version>
    </dependency>
<!--    mybitis整合spring-->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis-spring</artifactId>
      <version>2.0.6</version>
    </dependency>

    <!-- 做事务依赖-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-tx</artifactId>
      <version>5.2.5.RELEASE</version>
    </dependency>

<!--    jdbc依赖-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>5.1.5.RELEASE</version>
    </dependency>

    <!--druid数据源依赖 -->
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid</artifactId>
      <version>1.1.22</version>
    </dependency>

    <!--lombok依赖 -->
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.18.16</version>
    </dependency>

    <!--Mysql驱动 -->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>8.0.11</version>
    </dependency>

  </dependencies>

2.编写配置文件

spring主配置文件

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

    <!--声明jdbc属性文件 -->
    <context:property-placeholder location="classpath:db.properties"/>
    <!--声明数据源Datasource,作用是连接数据库 -->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
          init-method="init" destroy-method="close">
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
        <property name="maxActive" value="20"/>

    </bean>

    <!--声明的是mybatis中提供的SqlSessionFactoryBean类 ,这个类内部创建SqlSessionFactory的 -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--        配置主配置文件地址-->
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
<!--        注册mapper.xml-->
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!-- MapperScannerConfigurer:在内部调用getMapper()生成每个dao接口的代理对象。-->
    <bean id="mapperScanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
        <!--指定包名, 包名是mapper接口所在的包名。
         MapperscannerConfigurer会扫描这个包中的所有接口,把每个接口都执行
         一次getMapper()方法 ,得到每个接口的代理对象。
         创建好的代理对象放入到spring的容器中的。-->
        <property name="basePackage" value="com.ws.mapper"/>
    </bean>

    <context:component-scan base-package="com.ws.service"/>



</beans>

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>

    <settings>
        <!-- 打印查询语句 -->
        <setting name="logImpl" value="STDOUT_LOGGING" />

        <setting name="localCacheScope" value="SESSION"/>

        <!-- 控制全局缓存(二级缓存),默认 true-->
        <setting name="cacheEnabled" value="true"/>

        <!-- 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。默认 false  -->
        <setting name="lazyLoadingEnabled" value="true"/>
        <!-- 当开启时,任何方法的调用都会加载该对象的所有属性。默认 false,可通过select标签的 fetchType来覆盖-->
        <setting name="aggressiveLazyLoading" value="true"/>
        <!--  Mybatis 创建具有延迟加载能力的对象所用到的代理工具,默认JAVASSIST -->
        <!--<setting name="proxyFactory" value="CGLIB" />-->

    </settings>

    <typeAliases>
        <typeAlias alias="student" type="com.ws.vo.Student" />
    </typeAliases>


    <!--配置插件-->
<!--    <plugins>-->
<!--        <plugin interceptor="com.github.pagehelper.PageInterceptor">-->
<!--        </plugin>-->
<!--    </plugins>-->

    <mappers>
        <!--一个mapper标签指定 一个文件的位置。
           从类路径开始的路径信息。target/clasess(类路径 )
          -->
        <mapper resource="mapper/StudentMapper.xml"/>
    </mappers>



</configuration>

3.代码流程

实体类

@Data
public class Student implements Serializable {
    private Integer id;

    private String name;

    private Integer age;

    private Integer clazzNo;

    public Student(Integer id, String name, Integer age, Integer clazzNo) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.clazzNo = clazzNo;
    }

}

mapper接口

public interface StudentMapper {
    /**
     * 查询所有学生信息
     * @return
     */
//    List<Student> queryAllStudents(RowBounds rowBounds);
    List<Student> queryAllStudents();

    /**
     * 根据ID查学生信息
     * @return
     */
    Student querySyudentById(Integer id);

    /**
     * 添加学生
     * @return
     */
    int addStudent(Student student);

    /**
     * 修改学生信息
     * @return
     */
    int updateStudentById(Student student);

    /**
     * 删除学生
     * @return
     */
    int deletStudentById(Integer id);

//    /**
//     * 查询学生和班级
//     * @return
//     */
//    StudentAndClazz queryStudentAndeClazzById(Integer id);

}

mapper.xml

<?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.ws.mapper.StudentMapper">

    <cache type="org.apache.ibatis.cache.impl.PerpetualCache"
           size="1024"
           eviction="LRU"
           flushInterval="120000"
           readOnly="false"/>

    <select id="queryAllStudents" resultType="com.ws.vo.Student">
        select id, name, age, clazz_no from student
    </select>

    <select id="querySyudentById" parameterType="int" resultType="student">
        select id, name, age, clazz_no from student where id=#{id}
    </select>

    <insert id="addStudent">
        insert into student (id,name,age,clazz_no)values (#{id},#{name},#{age},#{clazzNo})
    </insert>

    <update id="updateStudentById" parameterType="student">
        update  student set name=#{name}, age=#{age}, clazz_no=#{clazzNo} where id=#{id}
    </update>

    <delete id="deletStudentById" parameterType="int">
        delete from student where id = #{id}
    </delete>

    <!-- 根据clazz_no查询clazz信息,一对一查询的结果,嵌套查询 -->
<!--    <resultMap id="studentAndClazz" type="com.ws.vo.StudentAndClazz">-->
<!--        <id column="id" property="id" jdbcType="INTEGER"/>-->
<!--        <result column="name" property="name" jdbcType="VARCHAR"/>-->
<!--        <result column="age" property="age" jdbcType="INTEGER"/>-->
<!--        <result column="clazz_no" property="clazzNo" jdbcType="INTEGER"/>-->
<!--        <result column="clazz_name" property="clazzName"/>-->
<!--    </resultMap>-->

<!--    <select id="queryStudentAndeClazzById" parameterType="int" resultMap="studentAndClazz">-->
<!--        select s.id, s.name, s.age, s.clazz_no, c.clazz_name from student s join clazz c on s.clazz_no=c.id where s.id = #{id}-->
<!--    </select>-->

<!--    <select id="queryStudentAndeClazzById" parameterType="int" resultType="com.ws.vo.StudentAndClazz">-->
<!--        select s.id, s.name, s.age, s.clazz_no clazzNo, c.clazz_name clazzName from student s join clazz c on s.clazz_no=c.id where s.id = #{id}-->
<!--    </select>-->


</mapper>

Service

@Service
public class StudentService {
    @Autowired
    public StudentMapper studentMapper;

    public List<Student> queryAllStudents() {
        return studentMapper.queryAllStudents();
    }
}

Test

public class App 
{
    public static void main( String[] args )
    {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        StudentService studentService = applicationContext.getBean(StudentService.class);
        List<Student> studentList = studentService.queryAllStudents();
        System.out.println(Arrays.toString(studentList.toArray())
                .replaceAll("\\[|\\]","")
                .replaceAll("\\)\\,","\\)\n"));
//        System.out.println(applicationContext.getBeanDefinitionNames());
    }
}

总结:

         Mybatis整合Spring实际上就是利用了Spring的扩展,所以我们要清楚Spring留给我们的钩子方法。一定要知道Spring注册bean的那几种方式。点击学习注册bean的方式

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

w7486

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值