前言
在使用MyBatis 之前,毫无疑问,我们要把它配置好!
application.properties:
server.port=8081
#==============================数据库相关配置==============================
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/数据库名称?
useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.datasource.username=数据库用户名
spring.datasource.password=数据库密码
#使用阿里巴巴druid数据源,默认使用自带的
#spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
#开启控制台打印sql
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
# mybatis 下划线转驼峰配置,两者都可以
#mybatis.configuration.mapUnderscoreToCamelCase=true
mybatis.configuration.map-underscore-to-camel-case=true
#配置扫描
mybatis.mapper-locations=classpath:mapper/*.xml
#配置xml的结果别名
mybatis.type-aliases-package=net.erpao.mybatis_demo.pojo
每个mapper.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="net.erpao.mybatis_demo.mapper.UserMapper">
<select id="findByUserId" resultType="User">
select * from user where id = #{user_id}
</select>
</mapper>
mybatis 下划线转驼峰配置,两者都可以
#mybatis.configuration.mapUnderscoreToCamelCase=true
mybatis.configuration.map-underscore-to-camel-case=true
#配置扫描
mybatis.mapper-locations=classpath:mapper/*.xml
#配置xml的结果别名
mybatis.type-aliases-package=net.xdclass.online_xdclass.model.entity
1.MyBatis 为什么最好声明 JdbcType
当SQL语句为 insert 或者 update 时,如果其变量含有 null 值,会报错:
###Cause: java.sql.SQLException: JZ006: Caught IOException: java.io.IOException: JZ0SL: Unsupported SQL type xxx.
是由于MyBatis在进行操作的时,会指定jdbcType类型的参数,如果参数为null 其类型默认设置为jdbcType.OTHER,导致数据库无法识别此格式。
解决方法就是给参数加上jdbcType,
例如:(#{title,jdbcType=VARCHAR}
因为MyBatis在执行SQL时会自动通过对象中的属性来去给SQL中参数进行赋值,它会自动将Java类型转换成数据库的类型。如果一旦传入了参数值是null 程序就无法准确判断这个类型应该是什么(是Integer?是VARCHAR?还是别的?),就有可能将类型转换错误,从而报错。
加入jdbcType正是为了解决这样的报错,需要针对这些可能为空的字段,手动指定其转换时用到的类型。
一般情况下,我们只需默认判定所有字段都可为空,即全部手动设置其转换类型即可,而无需去判断其每个字段是否可以为空。
2. MyBatis之foreach批量插入语法
<insert id="addBatch" parameterType="net.xdclass.online_class.domain.Video">
insert into video(`title`,`summary`,`cover_img`,`price`,`create_time`,`point`)
values
<foreach collection="list" item="video" separator=",">
(#{video.title,jdbcType=VARCHAR},#{video.summary,jdbcType=VARCHAR},#{video.coverImg,jdbcType=VARCHAR},
#{video.price,jdbcType=INTEGER},#{video.createTime,jdbcType=TIMESTAMP},#{video.point,jdbcType=DOUBLE})
</foreach>
</insert>
separator="," :去掉遍历的最后一个“,”
3.MyBatis之update更新语法
<update id="updateVideo" parameterType="net.xdclass.online_class.domain.Video">
update video
set
title = #{title,jdbcType=VARCHAR},
summary = #{summary,jdbcType=VARCHAR},
cover_img = #{coverImg,jdbcType=VARCHAR},
price = #{price,jdbcType=INTEGER},
create_time = #{createTime,jdbcType=TIMESTAMP},
point = #{point,jdbcType=DOUBLE}
where id = #{id}
</update>
4.Mybatis 动态字段更新 if test 标签的使用
作用:可以选择性更新⾮空字段
if 标签可以通过判断传⼊的值来确定查询条件,test 指定⼀个OGNL表达式
<update id="updateVideoSelective" parameterType="net.xdclass.online_class.domain.Video">
update video
<trim prefix="set" suffixOverrides=",">
<if test="coverImg != null">cover_img = #{coverImg,jdbcType=VARCHAR},</if>
<if test="price != 0">price = #{price,jdbcType=INTEGER},</if>
<if test="createTime != null">create_time = #{createTime,jdbcType=TIMESTAMP},</if>
<!--⼀定要看pojo类⾥⾯的是基本数据类型[int double],还是包装数据类型[Integer Double]-->
<if test="point != null">point = #{point,jdbcType=DOUBLE},</if>
</trim>
where id = #{id}
</update>
⼀定要看pojo类⾥⾯的是基本数据类型[int double],还是包装数据类型[Integer Double]
5.MyBatis 之删除语法和转义字符使用
需求:删除某个时间段之后 且⾦额⼤于 10元的数据
<delete id="deleteByCreateTimeAndPrice" parameterType="Map">
delete from video where create_time <![CDATA[ > ]]> #{createTime} and price <![CDATA[ <= ]]> #{price}
</delete>
问:为什么要转义字符呢?
答:因为MyBatis的 sql 写在XML⾥⾯, 有些 sql 的语法符号和 xml ⾥⾯的冲突
- ⼤于等于 <![CDATA[ >= ]]>
- ⼩于等于 <![CDATA[ <= ]]>
6.MyBatis之查询类别名typeAlias
类型别名,给类取个别名,可以不⽤输⼊类的全限定名。
如果有很多类,不⽤⼀个个配置,使⽤包扫描即可。
在 mybatis-config.xml 中配置:
<typeAliases>
<!--<typeAlias type="net.xdclass.online_class.domain.Video" alias="Video"/> 单个-->
<package name="net.xdclass.online_class.domain"/> <!--扫描包下的全部类,都以最后的类名作为别名-->
</typeAliases>
在VideoMapper.xml中:
<select id="selectByPointAndTitleLike" resultType="Video">
select * from video where point=#{point} and title like concat('%', #{title},'%')
</select>
7.高性能SQL之MyBatis3.X的SQL片段使用
SQL片段:根据业务需要,⾃定制要查询的字段,并可以复⽤
<sql id="base_video_field">
id,title,summary,cover_img
</sql>
<select id="selectById" resultType="Video">
select <include refid="base_video_field"/> from video where id = #{video_id,jdbcType=INTEGER}
</select>
8.MyBatis之resultMap
Mybatis的SQL语句返回结果有两种:
resultType:
- 查询出的字段在相应的pojo中必须有和它相同的字段对应,或者基本数据类型
- 适合简单查询
resultMap:
- 需要⾃定义字段,或者多表查询,⼀对多等关系,⽐resultType更强⼤
- 适合复杂查询
<resultMap id="VideoResultMap" type="Video">
<!--
id 指定查询列的唯⼀标示
column 数据库字段的名称
property pojo类的名称
-->
<id column="id" property="id" jdbcType="INTEGER"/>
<result column="video_title" property="title" jdbcType="VARCHAR"/>
<result column="summary" property="summary" jdbcType="VARCHAR"/>
<result column="cover_img" property="coverImg" jdbcType="VARCHAR"/>
</resultMap>
<select id="selectBaseFieldByIdWithResultMap" resultMap="VideoResultMap">
select id,title,summary,cover_img from video where id = #{video_id}
</select>
9.ResultMap复杂对象⼀对⼀查询结果映射之association
association: 映射到POJO的某个复杂类型属性,⽐如订单order对象⾥⾯包含 user对象
<resultMap id="VideoOrderResultMap" type="VideoOrder">
<!--
id 指定查询列的唯⼀标示
column 数据库字段的名称
property pojo类的名称
-->
<id column="id" property="id"/>
<result column="user_id" property="userId"/>
<result column="video_id" property="videoId"/>
<result column="video_title" property="videoTitle"/>
<!--
association:配置属性一对一
property:对应videoOrder里面的user属性名
javaType:这个属性的类型
-->
<association property="user" javaType="User">
<id column="user_id" property="id"/>
<result column="name" property="name"/>
<result column="head_img" property="headImg"/>
</association>
</resultMap>
<!--一对一关联用户订单,订单内部包含用户属性-->
<select id="queryVideoOrderList" resultMap="VideoOrderResultMap">
select
o.id,
o.user_id,
o.video_id,
o.video_title,
u.name,
u.head_img
from video_order o left join user u on o.user_id = u.id
</select>
// resultmap association关联查询
VideoOrderMapper videoOrderMapper = sqlSession.getMapper(VideoOrderMapper.class);
List<VideoOrder> videoOrderList = videoOrderMapper.queryVideoOrderList();
System.out.println(videoOrderList.toString());
10.ResultMap复杂对象⼀对多查询结果映射之collection
collection: ⼀对多查询结果查询映射,⽐如user有多个订单
<resultMap id="UserOrderResultMap" type="User">
<id column="id" property="id"/>
<result column="name" property="name"/>
<result column="head_img" property="headImg"/>
<!--
property 填写pojo类中集合类属性的名称
ofType 集合⾥⾯的pojo对象
-->
<collection property="videoOrderList" ofType="VideoOrder">
<id column="order_id" property="id"/> <!--配置主键,管理order的唯⼀标识-->
<result column="user_id" property="userId"/>
<result column="video_id" property="videoId"/>
</collection>
</resultMap>
<select id="queryUserOrder" resultMap="UserOrderResultMap">
select
u.id,
u.name,
u.head_img,
o.user_id,
o.video_id
from user u left join video_order o on u.id = o.user_id
</select>
// resultmap association关联查询
VideoOrderMapper videoOrderMapper = sqlSession.getMapper(VideoOrderMapper.class);
//resultmap collection测试
List<User> userList = videoOrderMapper.queryUserOrder();
System.out.println(userList.toString());