1.基础配置

导入依赖

<dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>

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

修改配置


需要注意,mysql5.x和mysql8.x的连接不同

网上上传代码的时候要注意自己的安全隐私,这里用的本地的数据库,就不进行特意处理了


mysql 8.x application.properties

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/springboot_learn?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&useSSL=true
spring.datasource.username=root
spring.datasource.password=123456

mybatis.type-aliases-package=com.zc.springbootMybatisLearn.entity.*
mybatis.mapper-locations=classpath*:mapper/*.xml

#开启sql日志功能
logging.level.com.xxxx.mapper:debug
#开启驼峰映射
contextLoads:33, SpringbootMybatisLearnApplicationTests

关于日志 可以去idea插件市场 下载Mybatis Log plugin插件

mysql5.x application.properties

jdbc.driver-class-name = com.mysql.jdbc.Driver
jdbc.jdbc-url = jdbc:mysql://localhost:3306/springboot_learn?useUnicode=true&characterEncoding=utf8&autoReconnect=true&failOverReadOnly

2.反向生成

使用mybatis-plugins插件可以实现自动生成

注意:自动生成使用驼峰原则,下划线后的字母变为大写,其他大写字母变为小写.

添加依赖:插件

<plugin>
                <groupId>org.mybatis.generator</groupId>
                <artifactId>mybatis-generator-maven-plugin</artifactId>
                <version>1.3.2</version>
                <configuration>
                    <verbose>true</verbose>
                    <overwrite>true</overwrite>
                </configuration>
            </plugin>

配置generatorConfig.xml

  • 只看和修改带序号的即可
  • 多次使用插件,xml里面的代码会叠加,记住删除或查看
  • 在table下面
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd" >
<generatorConfiguration >
    <!-- 1.此处需要添加自己的jar包安装位置-->
    <classPathEntry location="C:\Users\zhang\.m2\repository\mysql\mysql-connector-java\8.0.16\mysql-connector-java-8.0.16.jar" />
    <context id="context1" >

        <!-- optional,旨在创建class时,对注释进行控制 -->
        <commentGenerator>
            <property name="suppressDate" value="true"/>
            <property name="suppressAllComments" value="true"/>
        </commentGenerator>
        <!-- 2.此处为连接数据库,自己填写数据库的地址,用户名和密码-->
        <jdbcConnection driverClass="com.mysql.cj.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/springboot_learn?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&useSSL=true" userId="root" password="123456" />
        <!-- 此处为8.0以上版本的连接方式<jdbcConnection driverClass="com.mysql.cj.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/recruit?serverTimezone=UTC" userId="root" password="123456" /> -->       <!-- 非必需,类型处理器,在数据库类型和java类型之间的转换控制-->
        <javaTypeResolver>
            <property name="forceBigDecimals" value="false"/>
        </javaTypeResolver>

        <!-- 3.生成实体类的地方
        targetPackage     指定生成的实体类所在的包名
        targetProject     指定在该项目下所在的路径
        -->
        <javaModelGenerator targetPackage="com.zc.springbootMybatisLearn.entity"
                            targetProject="src/main/java">

            <!-- 是否允许子包,即targetPackage.schemaName.tableName -->
            <property name="enableSubPackages" value="false"/>
            <!-- 是否对model添加 构造函数 -->
            <property name="constructorBased" value="false"/>
            <!-- 是否对类CHAR类型的列的数据进行trim操作 -->
            <property name="trimStrings" value="true"/>
            <!-- 建立的Model对象是否 不可改变  即生成的Model对象不会有 setter方法,只有构造方法 -->
            <property name="immutable" value="false"/>
        </javaModelGenerator>

        <!--Mapper映射文件生成所在的目录 为每一个数据库的表生成对应的SqlMap文件 -->
        <!-- 4.生成mapper.xml的地方
        targetPackage     指定生成的实体类所在的包名
        targetProject     指定在该项目下所在的路径
        -->
        <sqlMapGenerator targetPackage="mapper" targetProject="./src/main/resources">
            <property name="enableSubPackages" value="true"/>
        </sqlMapGenerator>

        <!-- 客户端代码,生成易于使用的针对Model对象和XML配置文件 的代码
        type="ANNOTATEDMAPPER",生成Java Model 和基于注解的Mapper对象
        type="MIXEDMAPPER",生成基于注解的Java Model 和相应的Mapper对象
        type="XMLMAPPER",生成SQLMap XML文件和独立的Mapper接口
        -->
        <!-- 5.生成mapper接口的地方
        targetPackage     指定生成的实体类所在的包名
        targetProject     指定在该项目下所在的路径
        -->
        <javaClientGenerator targetPackage="com.zc.springbootMybatisLearn.mapper"
                             targetProject="src/main/java" type="XMLMAPPER">
            <property name="enableSubPackages" value="true"/>
        </javaClientGenerator>


        <!--数据库表反向映射到项目中-->
        <!-- 6.生成mapper接口的地方
        tableName 表名
        domainObjectName 生成的名 比如xx.java,xxMapper.java,xxMapper.xml
        -->
        <table tableName="book" domainObjectName="Book"
               enableCountByExample="false" enableUpdateByExample="false"
               enableDeleteByExample="false" enableSelectByExample="false"
               selectByExampleQueryId="false">
        </table>
    </context>
</generatorConfiguration>

3.mapper.xml

1.xml原本结构

这里简单写一个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.zc.springbootMybatisLearn.mapper.BookMapper">
  <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
    delete from book
    where id = #{id,jdbcType=INTEGER}
  </delete>
</mapper>
2.条件查询语句
<!--    1. parameterType 和 resultType 需要填写实体类的路径 -->
<!--    2.一般情况下:Integer判null ,String判断null和空字符串  -->
<select id="selectBySelective"  parameterType="com.zc.springbootMybatisLearn.entity.Book"
  resultType="com.zc.springbootMybatisLearn.entity.Book">
    select
    *
    from book
    where 1=1
    <if test="bookId != null" >
      and book_id=#{bookId,jdbcType=INTEGER}
    </if>
    <if test="name != null and name !=''" >
      and name = #{name,jdbcType=VARCHAR}
    </if>
  </select>
3.模糊查询
<if test="name != null" >
 name like  concat('%',#{name,jdbcType=VARCHAR},'%')
 </if>
4.mybtis 一些关键字
大于:">>
小于:<
大于等于:">>=
小于等于:<=
5.mybatis获得刚刚插入的主键
mapper使用注解实现
@Insert("  **     insert 插入语句         **")
    @Options(useGeneratedKeys = true,keyProperty = "bookId(此为对象的对应主键)",keyColumn = "book_id(数据库字段值)")
    int insertReturnPrimaryKey(Book record);
使用mapper.xml实现
<!-- useGeneratedKeys="true" keyProperty="id"(此处时参数值,不是table值)  -->
<insert id="save" useGeneratedKeys="true" keyProperty="bookId" parameterType="com.bootdo.business.domain.TableDO">
</insert>
service层
Mapper.insertReturnPrimaryKey(record);
 //record(插入的主体)
int id=record.getId();  //获得刚插入的主键
6.批量插入
批量插入
<!--       int batchInsert(List<Book> records);  -->
<insert id="batchInsert" parameterType="java.util.List">
    insert into book (book_id, `name`, author,
    press, pubdate, price, page, img, feature, booktype)
    values
    <foreach collection="list" item="records" separator=",">
      (#{records.bookId,jdbcType=INTEGER}, #{records.name,jdbcType=VARCHAR}, #{records.author,jdbcType=VARCHAR},
      #{records.press,jdbcType=VARCHAR}, #{records.pubdate,jdbcType=DATE}, #{records.price,jdbcType=DOUBLE},
      #{records.page,jdbcType=INTEGER}, #{records.img,jdbcType=VARCHAR}, #{records.feature,jdbcType=VARCHAR},
      #{records.booktype,jdbcType=INTEGER})
    </foreach>
  </insert>
批量修改
<!--     int batchUpdate(List<Book> records);   -->  
<update id="batchUpdate" parameterType="java.util.List">
    update book
    <trim prefix="set" suffixOverrides=",">
      <trim prefix="author = case" suffix="end,">
        <foreach collection="list" index="index" item="records">
          when book_id = #{records.bookId,jdbcType=INTEGER} then #{records.author,jdbcType=VARCHAR}
        </foreach>
      </trim>
    </trim>
    where book_id in
    <foreach close=")" collection="list" item="records" open="(" separator=", ">
      #{records.bookId,jdbcType=INTEGER}
    </foreach>
  </update>
批量修改/by selective
<!--     int batchUpdateSelective(List<Book> records); -->
  <update id="batchUpdateSelective" parameterType="java.util.List">
    update book
    <trim prefix="set" suffixOverrides=",">
      <trim prefix="name = case" suffix="end,">
        <foreach collection="list" index="index" item="records">
          <if test="records.name != null">
            when book_id = #{records.bookId,jdbcType=INTEGER} then #{records.name,jdbcType=VARCHAR}
          </if>
        </foreach>
      </trim>
    </trim>
    where book_id in
    <foreach close=")" collection="list" item="item" open="(" separator=", ">
      #{item.bookId,jdbcType=INTEGER}
    </foreach>
  </update>
in/not in
<!--     List<Book> selectByList(List<Integer> records);   -->
  <select id="selectByList" parameterType="com.zc.springbootMybatisLearn.entity.Book"
            resultType="com.zc.springbootMybatisLearn.entity.Book">
        select * from book
        where 1=1
        <if test="list!=null and list.size()>0 ">
            and book_id in
            <foreach collection="list" index="index" item="item"
                     separator="," open="(" close=")">
                #{item,jdbcType=INTEGER}
            </foreach>
        </if>
    </select>
forEach的用法详解

item			--->			集合中每一个元素进行迭代的别名
index			--->			表示迭代过程中,每次迭代的位置
open			--->			该语句以什么开始
separator		--->			在每次进行迭代之间以什么符号作为分隔符
close			--->			该语句以什么结束

最重要的是 collection这个字段

如果传入的是单参数且参数类型是一个 List 的时候,collection 属性值为 List;
 如果传入的是单参数且参数类型是一个 Array 数组的时候,collection 的属性值为 Array;
 如果传入的参数是多个的时候,我们就需要把它们封装成一个 Map 。

@param注解

相信学习mybatis肯定会遇到过下面的两种错误:

Parameter 'xxxList' not found. Available parameters are [Collection,list]

[Parameter '×××' not found. Available parameters are [0, 1, param1, param2]

  • 第一种错误: foreach的时候 Collection=“array” 或者’“list”,我们上面已经解决
  • 第二种错误: 多个参数的时候,mybatis将参数反射成[param1,param2]

以上两种情况,都是我们想直接使用参数名导致的错误,我们的想法肯定是希望在xml中直接使用参数名就可以获得参数获得的对象,但以上两种情况我们一种必须使用list/array,一种是param1,param2

在初学的时候,我们使用的解决方法是@param("参数名"),这样就可以直接使用参数名了

但是Java8之后,java给我们提供了一项便利,我们可以不需加@param就可以实现该功能,如果确定使用的java8,但依然没有该功能,可以去idea设置一下:

关于这个功能可以看该文章 :idea设置 -parameters

Springboot 配置shardingsphere的SQL 翻译_mysql

sql语句过长的问题

关于批处理查询的问题: 如果sql语句过长,那么可能会出现sql语句无法插入的问题,我们可以写一个方法,将一份List 分成多份,比如100个对象插入一次,这样sql语句就能减少100倍,效率依然得到很大提高,但不会再出现sql语句过长的情况出现了

//将List 分成多个List   
private static List<List<Object>> splitList(List<Object> messagesList, int groupSize) {
        int length = messagesList.size();
        // 计算可以分成多少组
        int num = (length + groupSize - 1) / groupSize; 
        List<List<Object>> newList = new ArrayList<>(num);
        for (int i = 0; i < num; i++) {
            // 开始位置
            int fromIndex = i * groupSize;
            // 结束位置
            int toIndex = (i + 1) * groupSize < length ? (i + 1) * groupSize : length;
            newList.add(messagesList.subList(fromIndex, toIndex));
        }
        return newList;
    }
service
@Override
    public PageBean findAll(实体对象 record, Page page) {
        com.github.pagehelper.Page<Object> pageHelper = PageHelper.startPage(page.getPageIndex(), page.getPageSize());
        List<实体对象> list = 实体Mapper.selectBySelective(record);
        //返回pageBean对象
        int pageNum = pageHelper.getPageNum();
        long total = pageHelper.getTotal();
        PageBean pageBean = new PageBean();

        if (total % pageHelper.getPageSize() == 0 && total / pageHelper.getPageSize() + 1 == pageNum) {
            com.github.pagehelper.Page<Object> pageHelper1 = PageHelper.startPage(page.getPageIndex() - 1, page.getPageSize());
            List<实体对象> list1 = 实体Mapper.selectBySelective(record);
            pageBean.setPage(String.valueOf(pageHelper1.getPageNum()));
            pageBean.setRows(list1);
            pageBean.setTotal(total);
        } else {
            pageBean.setPage(String.valueOf(pageNum));
            pageBean.setRows(list);
            pageBean.setTotal(total);
        }
        return pageBean;
    }
controller
import net.sf.json.JSONObject;
public String get实体对象(实体对象 record, Page page) {
        //   udcKpiFormulaService.addConn();
        PageBean list = 实体对象Service.findAll(record, page);
        String jsonString = JSONObject.fromObject(list).toString();
        return jsonString;
    }
controller传值时一定要传pageSize这个值
7.分页的问题

此处为之前编写的,本次没有测试,由于后面分页使用mybatis-plus,所以不再编写

service
@Override
    public PageBean findAll(实体对象 record, Page page) {
        com.github.pagehelper.Page<Object> pageHelper = PageHelper.startPage(page.getPageIndex(), page.getPageSize());
        List<实体对象> list = 实体Mapper.selectBySelective(record);
        //返回pageBean对象
        int pageNum = pageHelper.getPageNum();
        long total = pageHelper.getTotal();
        PageBean pageBean = new PageBean();

        if (total % pageHelper.getPageSize() == 0 && total / pageHelper.getPageSize() + 1 == pageNum) {
            com.github.pagehelper.Page<Object> pageHelper1 = PageHelper.startPage(page.getPageIndex() - 1, page.getPageSize());
            List<实体对象> list1 = 实体Mapper.selectBySelective(record);
            pageBean.setPage(String.valueOf(pageHelper1.getPageNum()));
            pageBean.setRows(list1);
            pageBean.setTotal(total);
        } else {
            pageBean.setPage(String.valueOf(pageNum));
            pageBean.setRows(list);
            pageBean.setTotal(total);
        }
        return pageBean;
    }
controller
import net.sf.json.JSONObject;
public String get实体对象(实体对象 record, Page page) {
        //   udcKpiFormulaService.addConn();
        PageBean list = 实体对象Service.findAll(record, page);
        String jsonString = JSONObject.fromObject(list).toString();
        return jsonString;
    }
controller传值时一定要传pageSize这个值