MyBatis

配置

首先在 pom.xml 引入 mybatis 依赖:

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

同时导入你要使用的数据库的驱动的依赖,这里以 MySQL 为例,我们要使用MySQL数据库就需要导入MySQL驱动的依赖:

<dependency>
 <groupId>com.mysql</groupId>
 <artifactId>mysql-connector-j</artifactId>
 <scope>runtime</scope>
</dependency>

接下来就是配置数据库的信息:
这里以MySQL 为例:

spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/mybatis_test?characterEncoding=utf8&useSSL=false
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver

把要操作的数据库的信息全部配置好,url、用户名、密码、驱动

创建实体类

根据我们要操纵的表创建好对应的实体类

回忆数据库建表规范:
我们使用统一使用小写字母,并且每一个单词之间使用下划线进行分割: user_name

回忆Java 构建 类 的规范
类名使用大驼峰的方式:UserInfo
属性和方法均使用小驼峰的方式: userName

我们根据表名和表内部的字段名来构建与之对应的类

其他配置:
我们还可以配置打印 mybatis 的日志信息

mybatis:
  configuration: # 配置打印 MyBatis⽇志
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

注解

@Select
@Insert
@Update
@Delete

示例:

    @Select("select * from user_info where id = #{id}")
    List<UserInfo> selectById(Integer id);

    @Insert("insert into user_info (username, `password`, age) values (#{username}, #{password}, #{age})")
    Integer insertUserInfo(UserInfo userInfo);

    @Update("update user_info set age = 100 where id = #{id}")
    Integer updateById(Integer id);

    @Delete("delete from user_info where id = #{id}")
    Integer deleteById(Integer id);

问题来了:
因为数据库的建表规范和Java的搭建类的规范是不相同的,那么我们如何让类的属性和数据库的表的字段进行一一匹配呢?

我们先来看看使用注解这种情况如何解决:

很简单,我们可以在 pom.xml 文件中导入 驼峰自动转换,只要你遵守上面的规范,spring 就会自动帮你进行转换。

mybatis:
  configuration: 
    map-underscore-to-camel-case: true #配置驼峰自动转换

第二种方式就是起别名,但是很麻烦,每次写 sql 语句都要起别名,将别名和类的属性对应起来:

@Select("select id, username, `password`, age, gender, phone, delete_flag as deleteFlag, " +
"create_time as createTime, update_time as updateTime from user_info")
public List<UserInfo> queryAllUser();

第三种方式是结果映射,通过 @Results 注解将 每一个表字段 和 类属性一一对应起来

    @Results(id = "baseMap", value = {
            @Result(column = "delete_flag", property = "deleteFlag"),
            @Result(column = "create_time", property = "createTime"),
            @Result(column = "update_time", property = "updateTime")
    })

如果想要使用上面 baseMap 的注解的话,我们使用 @ResultMap 来指定 即可

@ResultMap(value = "baseMap")
@Select("select * from user_info where id = #{id}")
List<UserInfo> selectById(Integer id);

XML

使用 XML 来书写 sql 语句的时候,我们首先要进行配置:

在 pom.xml 上配置好 xml 的路径,这样 spring 才会进行扫描

mybatis:
  mapper-locations: classpath:mapper/*Mapper.xml

在 rescources 文件夹下创建好 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="org.example.mybatis_demo.mapper.UserInfoMapperXML">
	//在此处写 sql 语句
<mapper>

namespace 是与之对应 的 类,就是 这个 XML 文件是为哪一个类提供 sql 语句的


其他建议:由于使用 xml 的方式来创建 sql 语句,为了方便我们知道这条 sql 语句对应的是哪一个方法,这里推荐使用 mybatis X 插件:

在这里插入图片描述
点击小鸟图标就会自动跳转到另一个与之对应的语句


示例:

    <select id="selectByName" resultType="org.example.mybatis_demo.model.UserInfo">
        select * from user_info where username = #{name}
    </select>
    <insert id="insertUserInfo">
        insert into user_info (username, `password`, age, gender, phone, delete_flag)
        values (#{username}, #{password}, #{age}, #{gender}, #{phone}, #{deleteFlag})
    </insert>

还是一样的问题来了:
因为数据库的建表规范和Java的搭建类的规范是不相同的,那么我们如何让类的属性和数据库的表的字段进行一一匹配呢?

我们来看XML 这种方式如何解决?

第一种解决方式还是和上面的一样,我们可以在 pom.xml 文件中导入 驼峰自动转换,只要你遵守上面的规范,spring 就会自动帮你进行转换。

mybatis:
  configuration: 
    map-underscore-to-camel-case: true #配置驼峰自动转换

第二种方式就是起别名,但是很麻烦,每次写 sql 语句都要起别名,将别名和类的属性对应起来。

第三种方式是结果映射,通过 resultMap 将 每一个表字段 和 类属性一一对应起来

    <resultMap id="BaseMap" type="com.example.demo.model.UserInfo">
        <id column="id" property="id"></id>
        <result column="delete_flag" property="deleteFlag"></result>
        <result column="create_time" property="createTime"></result>
        <result column="update_time" property="updateTime"></result>
    </resultMap>

如果想要使用上面 BaseMap 的注解的话,我们需要进行指定

<select id="queryAllUser" resultMap="BaseMap">
 select id, username,`password`, age, gender, phone, delete_flag, create_time, update_time 
 from user_info
</select>

在这里插入图片描述

#{} 和 ${}

先观察:使用 #{}

    @Select("select * from user_info where id = #{id}")
    List<UserInfo> selectById(Integer id);

在这里插入图片描述

通过观察 mybatis 日志,我们会发现 #{} 会变成 ? 进行占位


如果我们使用 ${} ,数值就会直接替换

    @Select("select * from user_info where id = ${id}")
    List<UserInfo> selectById(Integer id);

在这里插入图片描述


结论:#{} 是 预编译 sql,${} 是运行时 sql,预编译 sql 的性能会更好一些
${} 会存在 sql 注入的风险

但是并不是说 ${} 就没有任何用处,例如有一个业务的场景需要用到 数据库的排序操作,这时候我们需要传入 desc 或者 asc 字符串的时候,#{} 就不能完成,因为 #{} 是不可以成为 sql 命令的一部分,只能作为数据来进行填充,这时候只能使用 ${} 来进行,只要我们对外界不提供输入字符串的功能,而是使用类似按键的功能让用户选择升序还是降序排序,这样我们就可以避免 ${} 产生的 sql 注入问题

使用 like 关键字来进行模糊查询的时候,#{} 会报错,这时候需要使用 ${} ,为了避免产生sql 注入,我们可以使用内置函数 concat 来处理

@Select("select id, username, age, gender, phone, delete_flag, create_time, 
update_time " +
 "from user_info where username like concat('%',#{key},'%')")
List<UserInfo> queryAllUserByLike(String key);

动态 SQL

在传入数据库的数据,有些字段可以是非必填,这时候我们需要灵活地处理我们的 sql 语句,那么就需要用到动态 sql

这里使用 XML 的方式来进行演示:

< if > :和 if 语句一样的效果,如果满足 if 条件,就会添加 if 标签内部的 sql

    <insert id="insertUserInfo2">
        insert into user_info (
            <if test="username!=null">
                username,
            </if>
            <if test="password!=null">
                `password`,
            </if>
            <if test="age!=null">
                age,
            </if>
            <if test="gender!=null">
                gender
            </if>
        ) values (
            <if test="username!=null">
                #{username},
            </if>
            <if test="password!=null">
                #{password},
            </if>
            <if test="age!=null">
                #{age},
            </if>
            <if test="gender!=null">
                #{gender}
            </if>
            )
    </insert>

但是上面的语句有个问题,如果 gender 为空,但是前面的字段不为空, 那 sql 就会出现问题,你会发现多了一个逗号,这是一个非法的 sql:

insert into user_info username, `password`, age,  values (?, ?, ?, )

这时候就要用到 tirm 标签:

		 <trim prefixOverrides="," suffixOverrides="," prefix="(" suffix=")">
            <if test="username!=null">
                username,
            </if>
            <if test="password!=null">
                `password`,
            </if>
            <if test="age!=null">
                age,
            </if>
            <if test="gender!=null">
                gender
            </if>
        </trim>

prefixOverrides 表示去除前面的什么符号
suffixOverrides 表示去除后面什么符号
prefix 最前面使用什么符号
suffix 最后面使用什么符号

这样我们就可以避免 if 标签出现的 逗号问题了


where 标签:
如果有 where 语句的话,可以使用 where 标签来包裹,但是注意在删除,更新这两个操作的时候必须添加 where 语句,避免误删或者全部更新整张表,因此在删除和更新上面我们不推荐使用 where 标签

<select id="selectAllById" resultType="org.example.mybatis_demo.model.UserInfo">
        select * from user_info
        <where>
             id = #{id}
        </where>
    </select>

foreach 标签:通常用来遍历数组、链表等多数据的情况

            <foreach collection="list" separator="or" item="user">
                id = #{user}
            </foreach>

collection 指你要遍历的数组或者链表的名称(自定义,你自己随意,这里没有任何约束)
separator 表示每组数据使用什么来进行分割
item 表示每一个元素的名称(自定义,你自己随意,这里没有任何约束)


set 标签,这是使用在 更新语句上的标签

    <update id="updateUserInfoByName">
        update user_info
        <set>
            <if test="password!=null">
                `password` = #{password},
            </if>
            <if test="gender!=null">
                gender = #{gender},
            </if>
            <if test="deleteFlag!=null">
                delete_flag = #{deleteFlag}
            </if>
        </set>
        where
            username = #{username}
    </update>

include 和 sql 标签:
在编写 sql 语句,如果我们发现有很多sql 片段重复出现,我们可以使用 sql 标签来进行封装:

例如我们的更新语句频繁书写,我们使用 sql 来对 前半部分的 sql 片段来进行封装,使用 id 来指定该片段的名称,便于后续的调用

    <sql id="update1">
        update user_info
    </sql>

然后我们使用 include 标签来进行 sql 标签内的 sql 语句的调用:通过 id 来绑定 sql 标签的内容

    <update id="updateById2">
        <include refid="update1"></include>
        <set>
            <if test="password!=null">
                `password` = #{password},
            </if>
            <if test="age!=null">
                age = #{age}
            </if>
        </set>
        where id = #{id}
    </update>

这里不推荐使用 注解的方式来写 动态sql ,因为会变成一坨,书写的时候还没有提示:
使用注解和上面的 XML 是一样的语法:

@Select("<script>select id, username, age, gender, phone, delete_flag, 
create_time, update_time" +
 " from userinfo" +
 " <where>" +
 " <if test='age != null'> and age = #{age} </if>" +
 " <if test='gender != null'> and gender = #{gender} </if>" +
 " <if test='deleteFlag != null'> and delete_flag = #
{deleteFlag} </if>" +
 " </where>" +
 "</script>")
List<UserInfo> queryByCondition(UserInfo userInfo);

十分建议使用 XML 的方式来写动态sql

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值