MyBatis重难点

前言

在使用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());
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

二炮

你的鼓励将是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值