• IDEA07:Mybatis和Springboot操作数据库


    写在前面

    这里介绍如何使用Mybatis操作数据库。

    • Mybatis是一种操作数据库的框架,比JDBC要方便。
    • Mybatis通常会和Spring结合使用。借助Spring的依赖注入/控制反转,数据库的相关操作会更加简洁高效。
    • Springboot是Spring及其相关组件的集大成者,可以高效地配置Spring框架,避免繁琐的配置过程。
    • 有关Spring的介绍可以看:Spring和SpringMVC总结篇spring 与 springmvc 的区别和定义
    • 详细的介绍可以看:Spring 常见面试题总结

    一、SpringBoot框架层次

    因为Mybatis最好还是和Spring框架结合来使用,作为Spring的持久层来完成数据库操作,所以这里首先介绍一下Springboot的基本层次。

    • Entity/POJO层:实体层。定义数据表对象,是最基本的类。类一般需要提供和数据表属性对应的成员变量,以及对应的GET和SET方法。
    • Dao/Mapper层:持久层。创建和数据库交互的接口,SQL的操作依赖于这一层。通常是在xxxMapper.xml中写好SQL语句,然后在这一层绑定接口,后续可以通过这一层的接口调用数据库操作。
    • Service层:业务层。可以在持久层上面继续加功能复杂化,完成某种数据库操作的完整功能。但它仍然是专注于单独一种数据库操作,如更新或者查询等,通常不会调用多个持久层接口。
    • Controller层:控制层。实现具体的业务逻辑,不只是涉及数据库操作,还有视图控制和具体业务逻辑实现。这一层通常是调用Service层接口实现数据库操作。

    Springboot(或者说是SpringMVC)相当于使用了实体层、持久层和业务层三层来完成数据库操作。控制层相当于普通JAVA程序的main或者实现某种特定功能的函数。

    二、使用Springboot框架

    1.导入Maven

    <parent>
       <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-parentartifactId>
        <version>2.7.2version>
        <relativePath/> 
    parent>
    
    <dependencies>
        
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>
        
        <dependency>
            <groupId>org.mybatis.spring.bootgroupId>
            <artifactId>mybatis-spring-boot-starterartifactId>
            <version>2.2.2version>
        dependency>
    
    dependencies>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 最基础的配置是一个和两个依赖;
    • 意味着本项目不能使用它所代表的类,只能使用它所依赖的类,也就是中的类;
    • 表明本项目既可以使用它所代表的类,也可以使用它所依赖的类;
    • 其余的依赖可以参考博客:spring boot的maven配置依赖详解

    2.项目文件目录结构

    项目文件目录结构

    • main文件夹用来写正式的类,test文件夹用来写测试的类;
    • test文件夹中的类能够调用main中定义的类,但main中的类不能调用test中定义的类;
    • 最好是定义一个有含义的包名,一般是类似于倒写的域名,如xxx.xxx.xxx格式,而不要直接在java文件夹下创建类;
    • 包名类似于C++中的命名空间,可以分开不同功能和目的的同名函数,方便管理;
    • 按照Springboot框架的层次,定义四个包;
    • 增加一个util包用来写自定义的功能性组件;
    • Springboot程序入口是SpringbootMain类,配置文件是application.yml
    • resources下的mapper是用来保存真正的数据库映射xml文件的,每个xml和持久层的xxxMapper类一一对应。

    三、Springboot配置文件

    server:
      port: 8081
    
    mybatis:
      type-aliases-package: cn.jeremy.xxx.entity
      mapper-locations: classpath:mapper/*.xml
      configuration:
        map-underscore-to-camel-case: false
        
    spring:
      datasource:
        url: jdbc:sqlserver://xxx:1433;DatabaseName=xxx;encrypt=true;trustServerCertificate=true
        driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
        username: xxx
        password: xxx
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • application.yml中进行Springboot、database和mybatis的配置;
    • 当然也可不用application.yml而用application.properties来配置,但yml写起来更省事一点,两者其实也很容易相互转换;
    • type-aliases-package配置是要写上所有需要使用Mybaitis管理的实体类(也就是数据表对应的对象)所在包,多个包可用逗号分隔;
    • mapper-locations用来写xxxMapper.xml的路径,classpath就是指resources文件夹下的根路径;
    • map-underscore-to-camel-case用来进行数据库表属性和实体类的成员变量之间的自动映射,如果关闭了需要手动进行映射;
    • 注意:Springboot默认使用8080端口,这会和Zookeeper默认端口以及其他的Web应用冲突,所以最好是换一个端口,如8081。

    四、持久层的Mybatis实现

    前面已经提到了,Mybatis是Springboot的持久层框架,所以Springboot的持久层这里是采用Mybatis来实现(虽然持久层也可以用别的框架来实现,不局限于Mybatis)。整个Springboot框架的完整示例可以参考:Spring Boot 集成 MyBatis和 SQL Server实践IDEA创建Spring Boot项目,这里重点描述持久层的Mybatis实现。持久层的Mybatis实现需要同时完成接口和xml两个部分。

    1.Dao/Mapper包中的接口实现:

    package cn.jeremy.xxx.dao;
    
    import cn.jeremy.xxx.entity.Report;
    import org.apache.ibatis.annotations.Mapper;
    import org.apache.ibatis.annotations.Param;
    
    import java.util.List;
    
    @Mapper
    public interface ReportMapper {
        public List<Report> selectAll();
    
        public Report selectOne(@Param("uid")String uid);
    
    	public int updateStatus(@Param("uid")String uid, @Param("status") int status);
    
        public int updateUpdateAt(@Param("uid")String uid, @Param("current") String current);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 定义和实体层对应的Mapper接口,使用@Mapper注解;
    • 定义select、update和delete成员函数,这些函数均对应一个数据库操作,但并不使用Java来显式实现,而是在xml文件中实现,再由Mybatis代为管理,自动注入到类对象中;
    • @Param用来映射Java函数参数与xml参数之间的对应关系;

    2.xml文件中的映射实现

    
    DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    <mapper namespace="cn.jeremy.xxx.dao.ReportMapper">
        <resultMap id="resultMap" type="cn.jeremy.pdf_extractor.entity.Report">
            <id property="uid" javaType="java.lang.String" column="uuid" jdbcType="CHAR">id>
            <result property="name" javaType="java.lang.String" column="name" jdbcType="CHAR">result>
            <result property="status" javaType="java.lang.Integer" column="status" jdbcType="INTEGER">result>       
            <result property="updateAt" javaType="java.sql.Timestamp" column="lastupdate_at" jdbcType="TIMESTAMP">result>        
        resultMap>
    
        <sql id="Base_Column_List">
            uuid, status, lastupdate_at
        sql>
    
        <select id="selectAll" resultMap="resultMap">
            select * from xxx
        select>
    
        <select id="selectOne" resultMap="resultMap">
            select <include refid="Base_Column_List"/> from xxx
            where uuid = #{uid, jdbcType=CHAR}
        select>
    
        <update id="updateStatus">
            update xxx
            set status = #{status, jdbcType=INTEGER}
            where uuid = #{uid, jdbcType=CHAR}
        update>
    
        <update id="updateUpdateAt">
            update xxx
            set update_at = '#{current, jdbcType=TIMESTAMP}'
            where uuid = #{uid, jdbcType=CHAR}
        update>
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 文件开头的两行不能省略;
    • namespace表明了该xml文件是和哪个持久层接口对应;
    • resultMap是映射java变量和数据库表属性的关键,它给出了实体层类变量和属性之间的一一对应关系,可以定义了之后在下面的增删查改标签中直接引用;
    • SQL Server数据属性和Java数据类型的对应可以参考博文:sqlserver与java数据类型对应
    • Java类型和jdbcType的对应可以参考博文:JdbcType