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
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这个值