JAVA基础springboot

MyBatis中通过package标签加载mapper映射文件的

2019-01-05  本文已影响155人  叩丁狼教育

本文作者:孔维胜,叩丁狼高级讲师。原创文章,转载请注明出处。

MyBatis中通过package标签加载mapper映射文件的方式分析

看文章前的要求

在学习MyBatis的初级篇之前,有两个前提要求,第一.必须学会使用IDEA,因为在文章中,使用的工具为IDEA,文章中的案例也都是基于IDEA的。第二.必须学会使用MAVEN,因为在案例中需要的jar包,都是通过MAVEN来管理的。

文章中的案例的开发环境

JDK 1.8

IDEA 2017.3

MySQL 5.1.38

Apache Maven 3.5.0

Tomcat 9.0.6

MyBatis 3.4.6

案例需要的表和数据

我们使用MyBatis的目的最终是访问数据库,所以在数据库方面,我们先创建相应的数据库,表,导入相关的数据。如:

1.创建mybatis数据库。

2.在mybatis数据库中创建department(部门表)。

DROP TABLE IF EXISTS `department`;
CREATE TABLE `department` (
  `id` bigint(10) NOT NULL AUTO_INCREMENT COMMENT '部门ID',
  `name` varchar(20) DEFAULT NULL COMMENT '部门名称',
  `sn` varchar(20) DEFAULT NULL COMMENT '部门缩写',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

3.准备department(部门表相关的数据)

INSERT INTO `department` VALUES (1, '人力资源', 'HR_DEPT');
INSERT INTO `department` VALUES (2, '销售部', 'SALE_DEPT');
INSERT INTO `department` VALUES (3, '开发部', 'DEVELOP_DEPT');
INSERT INTO `department` VALUES (4, '财务部', 'FINANCE_DEPT');

案例需求

需求:使用Mapper动态代理的方式完成所有数据的查询操作。

需求分析

要使用MyBatis框架,首先需要导入mybatis的核心包,MyBatis主要是操作数据库,替换掉传统的JDBC方式访问数据库,所以需要导入mysql的驱动包。我们要在项目中使用单元测试进行测试,所以需要导入junit包,我们不想写javaBean的setter和getter方法,可以导入lombok的包。

我们使用MyBatis框架,需要两个配置文件,一个是MyBatis的主配置文件,主要用来配置事务管理器和数据库的连接信息,一个是封装SQL语句Mapper映射文件。我们为了数据库的连接信息不写死在主配置文件中,所以我们采用抽取的方式,把连接数据库的信息抽取到db.properties文件中,进行管理。通过package扫描的方式在主配置文件中挂载mapper的文件。如:

   <package name="cn.wolfcode.mapper"/> 

可能查询数据需要查询条件有很多,查询数据需要封装到对象中,所以我们可以定义一个JavaBean,来封装条件和查询的数据。

定义一个接口,编写操作数据库方法。方法的名字保持和sql映射文件中的标签的id一一对应。

通过加载主配置文件来获取SqlSessionFactory工厂对象,一般工厂对象都是单例模式的,所以这个操作只需要做一次即可。比如:我们不能每吃一次饭,都去建一所餐厅。两者的道理是一样的。

而在MyBatis的官网给出的建议是SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由对它进行清除或重建。因此 SqlSessionFactory 应该使用其单例模式,只创建一次在整个应用中,都可以使用。

工厂对象的获取思考:

那么把获取工厂对象的操作放在哪里合适呢?如果在本类中进行抽取,放在一个方法中,但是每个DAO的实现类都这样处理,还是会出现代码的冗余。所以最合适的方式定义一个MyBatisUtil工具类,把获取工厂对象的操作抽取到工具类中,那么工厂对象的获取只需要获取一次即可,所以在工具类中,定义在哪里,只会执行一次呢?静态代码块,我们都知道,类中的静态代码块,只会随着类的加载而加载,并且只执行一次。

MyBatis工具类设计思考:

何为工具类,一般我们在定义的工具类的时候,希望使用者只使用而不要修改此类,所以我们会设置这个类使用final进行修饰,这样这个类就是终结类,不能被继承。一般工具类不会让使用者去创建对象,而是采用提供静态方法的方式共使用者调用。

SqlSession对象获取思考:

定义一个方法供外部访问,获取SqlSession对象。这个方法设计成静态的这样,调用方法的时候不用再创建工具类对象。

定义一个测试类,编写一个测试方法,通过调用工具类中的方法获取SqlSession对象,通过SqlSession对象调用getMapper方法获取对应的Mapper的代理对象,然后调用接口中的方法获取所有数据。

案例代码

pom.xml:

 <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.4.6</version>
    </dependency>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.40</version>
    </dependency>
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.16.20</version>
    </dependency>

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>
   <properties  resource="db.properties"/>
   <typeAliases>
        <package name="cn.wolfcode.domain"/>
    </typeAliases>
    <environments default="dev">
        <environment id="dev">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driverName}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${userName}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>    
    <mappers>
       <package name="cn.wolfcode.mapper"/>
    </mappers>

</configuration>

db.properties:

driverName=com.mysql.jdbc.Driver
url=jdbc:mysql:///mybatis
userName=root
password=root123

DepartmentMapper.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="cn.wolfcode.mapper.DepartmetMapper">

    <!--
     select 表示查询语句的标签。标签体的内容即是查询的SQL语句
          id:SQL语句的唯一标识
          parameterType:传入这条SQL语句的参数的类的完全限定名或别名,
                 因为 MyBatis 可以通过 TypeHandler 推断出具体传入语句的参数,故可以省略
          resultType:返回期望的类型(类的完全限定名或别名),用来接收查询的结果。

      -->
    <select id="selectAll" resultType="cn.wolfcode.domain.Department">
        SELECT id,name,sn FROM department
        WHERE id = #{id}
    </select>

</mapper>

Department:

@Getter
@Setter
@ToString
public class Department {

    // 主键id
    private Long id;
    // 部门名称
    private String name;
    // 部门简写
    private String sn;
}

DepartmentMapper:

public interface DepartmentMapper {

   /**
     *  查询所有部门信息
     * @return 返回所有部门信息的集合
     */
    List<Department> selectAll();
}

MyBatisUtil:

public final class MyBatisUtil {

    private static SqlSessionFactory factory = null;

    static {
        // 使用static静态代码块,随着类的加载而加载,只执行一次
        try {
            // 加载MyBatis的主配置文件
            InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
            // 通过构建器(SqlSessionFactoryBuilder)构建一个SqlSessionFactory工厂对象
            factory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 获取sqlSession对象
    public static SqlSession openSession() {
        return factory.openSession();
    }
}

DepartmentMapperTest:

public class DepartmentMapperTest {
 @Test
    public void testQueryOne(){
        // 获取sqlSession对象
        SqlSession sqlSession = MyBatisUtil.openSession();
        // 获取Mapper对象
        DepartmentMapper departmentMapper = sqlSession.getMapper(DepartmentMapper.class);
        List<Department> departmentList = departmentMapper.selectAll();
        // 关闭资源
        sqlSession.close();
        // 遍历结果
  departmentList.stream().forEach(System.out::println);
    }

DepartmentMapper文件加载流程分析

XMLConfigBuilder.png Configuration.png MapperRegistry.png MapperRegistry.png MapperAnnotationBuilder.png MapperAnnotationBuilder.png XMLMapperBuilder.png

DepartmentMapper文件加载整体流程图

Mapper映射文件通过package方式解析流程图.png

想获取更多技术干货,请前往叩丁狼官网:http://www.wolfcode.cn/all_article.html

上一篇下一篇

猜你喜欢

热点阅读