Spring整合mybatis核心讲解

    技术2022-07-11  112

    一、首先我们先来看一下普通Mybatis的整合

    注:只是简单的提一下,非详细教程
    1.maven导入mybatis相应jar包(pom.xml):

    2.创建实体Entity(以User.java为例):
    public class User { private Integer id; private String name; private String password; public User() {} public User(Integer id, String name, String password) { this.id = id; this.name = name; this.password = password; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
    3.DAO层(UserDAO.java):
    public interface UserDAO { /** * 保存数据 */ void save(User user); }
    4.创建表:

    5.mybatis配置文件(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> <!--设置别名--> <typeAliases> <typeAlias alias="user" type="entity.User"/> </typeAliases> <!--连接池的配置--> <environments default="mysql"> <environment id="mysql"> <!--事务管理器 JDBC类型--> <transactionManager type="JDBC"> </transactionManager> <!--数据源--> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="username" value="root"/> <property name="password" value="root"/> <property name="url" value="jdbc:mysql://localhost:3306/test"/> </dataSource> </environment> </environments> <!--在这里注册Mapper文件--> <mappers> <mapper resource="mappers/UserDAOMapper.xml"/> </mappers> </configuration>
    6.mapper文件的配置(UserDAOMapper.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"> <!-- namespace:填写映射当前的Mapper接口,所有的增删改查的参数和返回值类型, 就可以直接填写缩写,不区分大小写,直接通过方法名去找类型--> <mapper namespace="dao.UserDAO"> <!--save方法进行数据插入操作 参数类型为user(即在mybatis-config.xml中设置的别名)--> <insert id="save" parameterType="user"> INSERT INTO user(name ,password) VALUES (#{name},#{password}) </insert> </mapper>
    7.最后进行测试(MybatisTest.java):
    import dao.UserDAO; import entity.User; 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 org.junit.Test; import java.io.IOException; import java.io.InputStream; /** * 记得导入junit包 * @author 17523 * Date:2020/7/1 22:14 */ public class MybatisTest { @Test public void test() throws IOException { //获取配置文件 InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml"); //创建会话工厂 SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream); //建立会话 SqlSession sqlSession = factory.openSession(); //获取接口的实例化对象 UserDAO userDAO = sqlSession.getMapper(UserDAO.class); User user = new User(); user.setName("zhangsan"); user.setPassword("123456"); userDAO.save(user); //提交事务 sqlSession.commit(); } }
    目录结构如下:

    最终效果:

    思考:

    关于mybatis,在书写时会出现两个问题:
    配置繁琐
    代码冗余
    具体表现如下:
    mybatis-config.xml文件,我们每书写一个映射(xxxMapper.xml),就需要在mybatis-config.xml文件中注册一次;我们每写一个实体,如果不想命名复杂,就需要在mybatis-config.xml文件中写一次别名,而且之后在分包开发的时候,可能会出现前面的包名一样,仅实体的名称不一样的情况,这样的配置是相当繁琐的。在以上代码的测试类(MybatisTest.java)中,我们在调用API的过程中,创建SqlSession的代码是固定的,都这么写,就产生了代码的冗余;在创建UserDAO的对象的时候,我们可以发现我们在获取的时候调用session.getMapper(xxx.class)方法,其中只是接口类型的不同,但是在实际开发过程中这样的代码会频繁的出现,我们频繁的调用也是造成了代码的冗余。
    那么,我们应该如何避免上述情况发生呢?

    二、spring整合的mybatis

    首先分析一下源码:

    - 对于以下代码(来自MybatisTest.java):

    //获取配置文件 InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml"); //创建会话工厂 SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);

    这是创建SqlSessionFactory的代码,最后成功获取到SqlSessionFactory的对象。为此,spring为我们准备了一个SqlSessionFactoryBean这个类,该类的作用就是用于封装创建SqlSessionFactory的代码(在配置的时候,由于是spring自己的类,我们就需要在applicationContext.xml文件中进行配置)。 可是,SqlSessionFactoryBean封装的内容包括原有的mybatis-config.xml,mybatis-config.xml主要的作用为:1.连接池的配置;2.类别名的配置(typeAlias);3.映射文件(xxxMapper.xml)文件的注册。我们怎样为其进行配置呢?

    序号mybatis-config.xml需要配置的内容SqlSessionFactoryBean中的参数1连接池的配置dataSource2类别名的配置typeAliasesPackage3映射文件注册mapperLocations 1.连接池配置: 如下图(注:直接使用druid连接池): 2.类别名配置: 其实根据参数也能发现,typeAliasesPackage多了一个Package,词如其名,我们仅需指定实体所对应的包即可,而别名就是包下所对应的类名。3.映射文件注册: 使用mybatis注册映射文件的时候,我们需要写一个xxxMapper.xml,再将其注册到mybatis-config.xml中,而现在,我们可以对映射文件进行通配的设置(如*Mapper.xml,这样就能匹配到—>UserDAOMapper.xml ProductDAOMapper.xml,这种情况下,只要以Mapper结尾,都可以自动注册)。

    - 对于以下代码(来自MybatisTest.java):

    //建立会话 SqlSession sqlSession = factory.openSession(); //获取接口的实例化对象 UserDAO userDAO = sqlSession.getMapper(UserDAO.class);

    基于SqlSessionFactory对象创建会话并不难,SqlSessionFactory对象已经获得了,只需要调用openSession()方法就可以创建sqlSession了;之后sqlSession调用getMapper()方法,传入接口的.class文件,就可以获得接口的对象。 对于以上两行代码,spring同样为我们提供了一个类:MapperScannerConfigure,该类的作用就是封装以上两行代码。

    序号以上两行代码的工作MapperScannerConfigure中的参数1建立会话sqlSessionsqlSessionFactoryBeanName2获得接口的实例化basePackage 1.建立会话sqlSession: 简单来讲就是利用之前SqlSessionFactoryBean这个类所做的封装,获取到这个叫做factory的SqlSessionFactoryBean对象,然后调用openSession()方法,有了factory,我们就能拿到sqlSession。spring使用MapperScannerConfigure对其进行封装,根据参数名sqlSessionFactoryBeanName,传入的参数应该是SqlSessionFactoryBean的名字,也就是这个类在spring工厂中定义的id(如上图id名称为ssfd)。 2.获得接口的实例化对象: 其实就是根据会话对象sqlSession的getMapper()方法,传入对应的xxxDAO.class文件,获取到xxxDAO的实例化对象。根据MapperScannerConfigure的参数名basePackage,可以得知传入的值应该是一个包路径(如dao包所在的路径) 总的来说,MapperScannerConfigure这个类最终就可以帮我们创建我们的DAO对象。但是,我们应该如何获得这个DAO对象呢? 我们曾经使用ctx.getBean(“bean的id值”)来获取对应的对象(ctx是ApplicationContext的实例对象),现在要获取这些DAO对象,我们需要指定id。这些id值,就是DAO接口首字母小写后的值(如要获取UserDAO的对象,其id值为userDAO)。

    OK,分析结束,开始编码:

    1.首先maven导入相应jar包:

    pom.xml完整文件:
    <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>groupId</groupId> <artifactId>spring-mybatis</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.4</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-context --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.2.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.0.10.RELEASE</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.48</version> </dependency> <!--spring整合mybatis需要用到的包--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.6</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.2.5.RELEASE</version> </dependency> <!--mybatis与spring整合所用的包--> <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.22</version> </dependency> </dependencies> </project>
    2.applicationContext.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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!--连接池--> <bean id="druid" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="username" value="root"/> <property name="password" value="root"/> <property name="url" value="jdbc:mysql://localhost:3306/test?useSSL=false"/> </bean> <!--SqlSessionFactoryBean--> <bean id="ssfb" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="druid"/> <!--指定实体类所在的包--> <property name="typeAliasesPackage" value="entity"/> <!--指定映射文件的路径 采用通用配置--> <property name="mapperLocations" value="mappers/*Mapper.xml"/> </bean> <!--MapperScannerConfigurer--> <bean id="scanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="sqlSessionFactoryBeanName" value="ssfb"/> <!--指定DAO接口所放置的包--> <property name="basePackage" value="dao"/> </bean> </beans>
    3.dao包下文件(UserDAO.java):
    package dao; import entity.User; public interface UserDAO { void save(User user); }
    4.entity包下文件(User.java):
    /** * @author 17523 * Date:2020/7/2 10:49 */ package entity; public class User { private Integer id; private String name; private String password; public User() {} public User(Integer id, String name, String password) { this.id = id; this.name = name; this.password = password; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
    5.resources/mappers/xxxMapper.xml文件(UserDAOMapper.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"> <!-- namespace:填写映射当前的Mapper接口,所有的增删改查的参数和返回值类型, 就可以直接填写缩写,不区分大小写,直接通过方法名去找类型--> <mapper namespace="dao.UserDAO"> <!--save方法进行数据插入操作 参数类型为User(实体类所在的包entity,别名为类名)--> <insert id="save" parameterType="User"> INSERT INTO user(name ,password) VALUES (#{name},#{password}) </insert> </mapper>
    6.测试(SpringMybatisTest.java):
    import dao.UserDAO; import entity.User; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * @author 17523 * Date:2020/7/2 10:42 */ public class SpringMybatisTest { /** * 用于测试spring与mybatis的整合 */ @Test public void test(){ ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); //接口的首字母的小写 UserDAO userDAO = (UserDAO) ctx.getBean("userDAO"); User user = new User(); user.setName("Lisi"); user.setPassword("asdfghjkl"); userDAO.save(user); } }
    目录结构如下:

    运行截图:

    最终效果:

    如有错误,欢迎指正!

    Processed: 0.023, SQL: 9