spring boot -- 整合Mybatis

前言

  在项目中,获取到数据库中的数据后,需要将其映射成class才能使用,一般的程序中都有上百个实体类,繁重且重复的赋值映射操作,是在让人不愉快。有没有一个东西可以自动帮我们处理实体类的映射操作,使我们的工作简化呢?

  现在市面上广泛使用两种解决方案

  1、Hibernate的 Spring Data Jpa

  2、Mybatis的:mybatis-spring-boot-starter

  它们的作用都是通过封装简化了开发人员对数据库的操作。本文主要讲的是Mybatis的使用,对Hibernate不做概述

mybatis官网

  了解更多细节,可以前往mybatis官方文档

使用mybatis与不使用mybatis的区别

  不使用mybatis

    我们对于executeQuery查询出来的数据,需要通过迭代ResultSet来读取,如果对象非常复杂,属性繁多,那么就需要定义一大堆的变量,重复使用一大堆方法(getInt、getString)

        Connection conn=  //...获取connection
        PreparedStatement ps = conn.prepareStatement("select * from user");
            ResultSet rs = ps.executeQuery();
            List<UserMap> list = new ArrayList<>();
            while (rs.next()) {
                UserMap um = new UserMap();
                um.id = rs.getInt("id");
                um.account = rs.getString("account");
                ...// 大量的赋值操作
            }

  使用mybatis

    只需要两步

      1、定义一个映射接口

@Mapper 
public interface Myb {
    
    @Select("SELECT * FROM user")
List<UserMap> getAll();
  
//实体类UserMap中的字段会自动被赋予,与sql语句查询结果相同列名的值,举例:UserMap中的存在属性字段id,那么会自动与sql执行结果中的id列的值进行绑定。当然也可以手动指定对应的列,详情请前往mybatis官方文档
}

      2、使用

    @Autowired
    private Myb my; //无需手动实现Myb接口,Mybatis已经自动实现,所以自动装载后直接使用即可

    @RequestMapping("login")
    public Object index() {
        List<UserMap> listUser = my.getAll();//直接getAll方法,获取到通过sql select * from user查询到的数据映射结果
        return listUser;
    }

  总结

    不使用mybatis

      1、需要定义PreparedStatement 、Connection、ResultSet对象,并处理响应的异常

      2、需要迭代ResultSet对象,将executeQuery查询出来的数据手动转化车class对象,如果数据结构复杂,那么整个项目成百上千个Class映射,会产生大量重复劳动的工具量,以及大量重复代码

如何使用mybatis

    mybatis的使用有两种方式,注解方式和xml方式

=============注解方式====================

  1、下载依赖

     //mybatis没有集成jdbc,所以对不同数据库的链接,还是需要对应的库
     <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.26</version> </dependency>

    //mybatis     <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.0.0</version> </dependency>

  2、配置application.yml

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/test?allowMultiQueries=true&autoReconnect=true&characterEncoding=utf-8
    username: root
    password: root

  3、定义Mapper

@Mapper //表明此接口是一个mapper,加上此注解会自动被spring boot扫描到
public interface Myb {
    //在接口中定义一个返回UserMap类型数据方法,会根据定义的数据类型,去映射数据
    @Select("SELECT * FROM user")
    List<UserMap> getAll();//定义执行sql,会将sql执行的结果映射到getAll()的return中
}

     (1)也可以不使用@Mapper注解,在启动类上使用@MapperScan("com.example.mybitesstudy02.service"),指定扫描的包

//@Mapper //去掉@Mapper
public interface Myb {

  @Select("SELECT * FROM user") List<UserMap> getAll(); }
@MapperScan("com.example.mybitesstudy02.service") //在启动类中指定扫描包
@SpringBootApplication
public class MybitesStudy02Application {

    public static void main(String[] args) {
        SpringApplication.run(MybitesStudy02Application.class, args);
    }

}

  4、调用

@RestController
public class Index {

    @Autowiredprivate Myb my; //无需手动实现Myb接口,Mybatis已经自动实现,所以自动装载后直接使用即可

    @RequestMapping("login")
    public Object index() {
        List<UserMap> listUser = my.getAll();//直接getAll方法,获取到通过sql select * from user查询到的数据映射结果
        return listUser;
    }
}

  (1)如果是使用@MapperScan指定扫描路劲的话,那么Autowired需要设置required=false

@RestController
public class Index {

    @Autowired(required = false) //使用@MapperScan无法在编译时注入my
    private Myb my; 

    @RequestMapping("login")
    public Object index() {
        List<UserMap> listUser = my.getAll();
        return listUser;
    }
}

 

=============xml方式====================

  因为依赖已经下载过了,所以我们直接跳过

  1.修改application.yml

  ...//旧的配置
    
#新增配置项
mybatis:
  # config-location: classpath:mybatis/mybatis.config.xml #指定Mybatis配置文件放置目录,学习阶段可以先不管他,
  mapper-locations: classpath:mybatis/sql/*Map.xml #指定映射xml文件放置目录,以及匹配规则

  2.在classpath:mybatis/sql目录下编写映射xml文件

<?xml version="1.0" encoding="UTF-8" ?>
<!--这个是必须要的 对xml文档进行标注功能-->
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<!--mapper 的namespace 要与你的映射接口的完整包名一致 -->
<mapper namespace="com.example.mybitesstudy02.service.Myb">

    <!--    定义一个接收的数据对象-->
    <!--    id 表明后续xml中使用的id-->
    <!--    type 为对应实体类的完整包名-->
    <resultMap id="UserMapXml" type="com.example.mybitesstudy02.service.UserMap">
        <id column="id" property="id"/>
        <result column="account" property="account"/>
    </resultMap>

    <!--    定义一个查询语句-->
    <!--    id 必须要与映射接口com.example.mybitesstudy02.service.Myb中的方法名一致,下例表示映射到com.example.mybitesstudy02.service.Myb 
    接口上的 getAll方法,返回一个id为UserMapXml的<resultMap>作为数据类型-->
    <select id="getAll" resultMap="UserMapXml">
        SELECT *
        FROM user
    </select>
</mapper>

  3、改造com.example.mybitesstudy02.service.Myb接口

package com.example.mybitesstudy02.service;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;

@Mapper //不使用@Mapper的话,可以在启动类使用@MapperScan指定扫描
public interface Myb {
//@Select("select * from user) 此注解可以不用了 List
<UserMap> getAll(); }

  4、造就使用即可

@RestController
public class Index {

    @Autowired //自动装载
    private Myb my;

    @RequestMapping("login")
    public Object index() {
        List<UserMap> um = my.getAll();
        return um;
    }
}

 一些问题

  BindingException 异常

    原因:

      1.mapper.xml文件的namespace与mapper接口完整包路径不一致

      解决方案:

        参照xml方式使用mybatis的第二步

      2.mapper.xml文件中的sql语句所在标签的id属性与mapper接口中的方法名称不一致

      解决方案:

        参照xml方式使用mybatis的第二步

      3.xml资源未被扫描到

      解决方案:

        修改pom.xml的build,使其能够扫描到Mybatis的映射xml放置的位置

 <build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
            </resource>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
            </resource>
        </resources>

    </build>
原文地址:https://www.cnblogs.com/wrhbk/p/15242973.html