前几节有点儿肝,虽然有复制粘贴代码但是每篇文章也记录了上万字,接下来内容分成两节记,分别是Spring整合mybatis和事务,这节先记录一下用Spring整合mybatis。

一、持久层的整合

JAVAEE的开发肯定避不开整合持久层,虽然有多种持久层选型比如JDBC、MyBatis、JPA(Hibernate)等,但是统一会遇到的问题就是持久层代码开发过程中存在冗余。所以Spring基于模板设计模式对于上述的持久层技术进行了封装。

模板模式后续有时间可以研究一下:《JAVA设计模式》之模板模式(Template)

Spring整合的持久层技术:

1. JDBC
 |- JDBCTemplate
2. Hibernate (JPA)
 |- HibernateTemplate
3. MyBatis
 |- SqlSessionFactoryBean MapperScannerConfigure

以下就用Mybatis举例子了,其实我平常用JPA和MBG比较多,传统的Mybatis开发早就忘了,简单再回顾一下:

建实体类,建DAO接口,建表,建mapper.xml文件,注册配置mapper.xml文件和配置连接池等等等等,最后用Mybatis的API再去创建会话,再去会话里调用具体业务逻辑并提交事务,烦得要死。

代码测试:

实例类略,建了有无参构造和get set;dao接口略,定义了一个方法。

Mybatis的配置文件,配置了连接池、实体别名、注册了mapper.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>
    <typeAliases>
        <typeAlias  alias="user"  type="com.jin.mybatis.User"/>
    </typeAliases>

    <environments default="mysql">
        <environment id="mysql">
            <transactionManager type="JDBC"></transactionManager>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/spring_mybatis?useSSL=false"/>
                <property name="username" value="root"/>
                <property name="password" value="1"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper resource="UserDAOMapper.xml"/>
    </mappers>
</configuration>

dao接口的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.jin.mybatis.UserDAO">
    <insert id="save" parameterType="user">
        insert into t_users(name,password) values (#{name},#{password})
    </insert>
</mapper>
package com.jin.mybatis;

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;

/**
 * @author jinyunlong
 * @date 2021/12/8 16:50
 * @profession ICBC锅炉房保安
 */
public class TestMyBatis {
    public static void main(String[] args) throws IOException {
        InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();

        UserDAO userDAO = sqlSession.getMapper(UserDAO.class);
        User user = new User();
        user.setName("opopop");
        user.setPassword("fdfdfdfd");
        userDAO.save(user);
        sqlSession.commit();

    }
}

测试方法,将实体对象内容插入表,提交事务。

将如上步骤分为7步:

1. 实体
2. 实体别名
3. 表
4. 创建DAO接⼝
5. 实现Mapper⽂件
6. 注册Mapper⽂件
7. MybatisAPI调⽤

可见除了步骤1、2、4、5必须以外,其他步骤都存在配置繁琐或者代码冗余的问题:

配置繁琐 代码冗余
1. 实体
2. 实体别名 配置繁琐
3. 表
4. 创建DAO接⼝
5. 实现Mapper⽂件
6. 注册Mapper⽂件 配置繁琐
7. MybatisAPI调⽤ 代码冗余

这时候使用Spring工厂可以解决以上两个问题。

二、Spring与MyBatis整合

12.PNG

整合思路如上图,可以通过把Spring包(org.spring.mybatis.xxx)里的类对象交由工厂管理并将上述配置繁琐的几点直接进行注入。创建dao对象的冗余代码也可以交由工厂配置文件解决,引入类对象并注入basePackage,dao对象的名字就是首字母小写,作为bean去被 getbean。

代码测试:

首先需要先引入依赖:

<dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.1.14.RELEASE</version>
        </dependency>

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

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

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.48</version>
        </dependency>

        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.6</version>
        </dependency>

最主要的就是配置文件,主要是看下面三个包(文件夹)的指定路径,分别对应实体包、mapper.xml储存文件夹、dao包。对应实体别名、注册mapper.xml、创建dao对象;因为是对目录的指定,所以只要写一次,目录中文件都会生效:

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:aop="http://www.springframework.org/schema/aop"
       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 http://www.springframework.org/schema/aop   http://www.springframework.org/schema/aop/spring-aop.xsd">

<!--    连接池-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://localhost:3306/spring_mybatis?useSSL=false"></property>
        <property name="username" value="root"></property>
        <property name="password" value="1"></property>
    </bean>

<!--    创建SqlSessionFactory  SqlSessionFactoryBean-->
    <bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"></property>
        <property name="typeAliasesPackage" value="com.jin.entity"></property>
<!--        指定 实体类所在的包 com.baizhiedu.entity User-->
<!--                                              Product-->
        <property name="mapperLocations">
            <list>
                <value>classpath:com.jin.mapper/*Mapper.xml</value>
<!--                指定 配置⽂件(映射⽂件)的路径 还有通⽤配置-->
<!--                com.baizhiedu.mapper/*Mapper.xml-->
            </list>
        </property>
    </bean>

<!--    创建DAO对象 MapperScannerConfigure-->
    <bean id="scanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactoryBean"></property>
        <property name="basePackage" value="com.jin.dao"></property>
<!--        指定 DAO接⼝放置的包 com.baizhiedu.dao-->
    </bean>
</beans>
package com.jin;

import com.jin.dao.UserDAO;
import com.jin.entity.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author jinyunlong
 * @date 2021/12/9 15:38
 * @profession ICBC锅炉房保安
 */
public class TestMybatisSpring {
    /*
    用于测试:Spring与Mybatis的整合
     */
    @Test
    public void test1(){
        ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");
        UserDAO userDAO = (UserDAO) ctx.getBean("userDAO");

        User user = new User();
        user.setName("llll");
        user.setPassword("232323");
        userDAO.save(user);
    }
}

返回结果:

13.PNG

直接工厂调用创建会话并获取对象,解决配置繁琐和代码冗余的问题。配置文件只需要歇一次,之后只要专注于以下4步的编写即可:

1. 实体
2. 表
3. DAO接⼝
4. Mapper⽂件配置

一个细节:Spring和Mybatis整合,事务是自动提交的:

本质上控制连接对象(Connection) ---> 连接池(DataSource)
1. Mybatis提供的连接池对象 ---> 创建Connection
 Connection.setAutoCommit(false) ⼿⼯的控制了事务 , 操作完成后,⼿
⼯提交
2. Druid(C3P0 DBCP)作为连接池 ---> 创建Connection
 Connection.setAutoCommit(true) true默认值 保持⾃动控制事务,⼀条
sql ⾃动提交
答案:因为Spring与Mybatis整合时,引⼊了外部连接池对象,保持⾃动的事务提交这
个机制(Connection.setAutoCommit(true)),不需要⼿⼯进⾏事务的操作,也能进
⾏事务的提交
注意:未来实战中,还会⼿⼯控制事务(多条sql⼀起成功,⼀起失败),后续Spring通过
事务控制解决这个问题。
三、总结

Spring整合Mybatis:IOC的应用,但不是解耦,是解决配置繁琐和代码冗余的问题。


标题:Spring(6)
作者:jyl
地址:http://jinyunlong.xyz/articles/2021/12/09/1639042100551.html