【JavaEE】Spring(6):Mybatis(下)


一、Mybatis XML配置文件

Mybatis开发有两种方式:

  1. 注解
  2. XML

之前讲解了注解的方式,接下来学习XML的方式

1.1 配置数据库连接和Mybatis

直接在配置文件中配置即可:

java 复制代码
spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/mybatis_test?characterEncoding=utf8&useSSL=false
    username: root
    password: root
    driver-class-name: com.mysql.cj.jdbc.Driver
mybatis:
  configuration:
    map-underscore-to-camel-case: true
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl 
  mapper-locations: classpath:mapper/**Mapper.xml #配置xml文件的路径

UserInfoXMLMapper.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.example.demo.mapper.UserInfoXMLMapper">

    <select id="queryAllUser" resultType="com.example.demo.model.UserInfo">
        select username,`password`, age, gender, phone from userinfo
    </select>
    
</mapper>

测试代码:

java 复制代码
@Test
void queryAllUser() {
    userInfoMapper.queryAllUser();
}

1.2 增(Insert)

xml文件:

XML 复制代码
<insert id="insertUser">
    insert into userinfo (username, `password`, age, gender, phone) 
    values (#{username}, #{password}, #{age},#{gender},#{phone})
</insert>

UserInfoXMLMapper接口:

java 复制代码
Integer insertUser(UserInfo userInfo);

返回结果是影响的行数

返回自增id:

XML 复制代码
<insert id="insertUser" useGeneratedKeys="true" keyProperty="id">
    insert into userinfo (username, `password`, age, gender, phone) 
    values (#{username}, #{password}, #{age},#{gender},#{phone})
</insert>

1.3 删(Delete)

xml文件:

XML 复制代码
<delete id="deleteUser">
    delete from userinfo where id = #{id}
</delete>

1.4 改(Update)

xml文件:

XML 复制代码
<update id="updateUser">
    update userinfo set username=#{username} where id=#{id}
</update>

1.5 查(Select)

在使用注解查询所有用户时,会遇到有属性没有被赋值的情况,我们的解决方案分别为:起别名、结果映射、 列名驼峰式命名

现在使用xml文件,解决方案仍然是这三个,其中第1个和第3个和注解的方式一样,这里主要讲解以下结果映射

XML 复制代码
<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>
<select id="queryAllUser" resultType="com.example.demo.model.UserInfo" resultMap="BaseMap">
    select id, username,`password`, age, gender, phone, delete_flag, create_time, update_time from userinfo
</select>

二、#{} 和 ${}的区别

#{}和${}都可以用来赋值,我们之前都用的#{},接下来看以下这两个的区别

1. 赋值的是Integer类型

首先是#{}

XML 复制代码
<select id="selectUserById" resultType="com.example.demo.model.UserInfo">
    select username, password, age, gender, phone from userinfo where id = #{id}
</select>

观察日志:

我们输入的参数并没有拼接到SQL语句中,而是用?作为占位符,我们称这种SQL为预编译型SQL

现在改成${}

XML 复制代码
<select id="selectUserById" resultType="com.example.demo.model.UserInfo">
    select username, password, age, gender, phone from userinfo where id = ${id}
</select>

此时我们输入的参数拼接到了SQL语句中

2. 赋值的是String类型

首先是#{}

XML 复制代码
<select id="selectUserByName" resultType="com.example.demo.model.UserInfo">
    select username, password, age, gender, phone from userinfo where username = #{username}
</select>

改为${}

XML 复制代码
<select id="selectUserByName" resultType="com.example.demo.model.UserInfo">
    select username, password, age, gender, phone from userinfo where username = ${username}
</select>

由于SQL语法中,字符串类型需要加上单引号,将参数直接拼接到SQL语句中是没有加单引号的,因此会报错

所以要在xml中手动加上单引号

${}存在SQL注入问题

SQL注入:通过输入的数据来修改事先定义好的SQL语句,以达到执行代码共计服务器的方式

举例:查询名字为 lisi 的用户信息,正常情况要手动加上单引号

我们输入lisi后,就可查到他的信息,但如果将输入改为**'or 1 = '1** ,将该参数拼接到SQL语句后:

可以看到通过这个查询条件可以查询到所有用户的信息

如果将密码验证的代码简单的写成 password = '${password}',此时如果密码写 'or 1 = '1,就可以直接登录成功

2.1 排序功能

{}存在SQL注入问题,但也不是一点没用,其中排序就需要用到{}

XML 复制代码
<select id="selectAllUserBySort" resultType="com.example.demo.model.UserInfo">
    select username, password, age, gender, phone from userinfo order by id ${sort}
</select>

执行测试代码

java 复制代码
@Test
void selectAllUserBySort() {
    userInfoXMLMapper.selectAllUserBySort("desc");
}

如果使用#{},由于参数类型为String,在查询时,desc前后会自动加上单引号,但排序并不需要单引号,所以会出错

2.2 like 查询

like 使用#{}报错

java 复制代码
@Select("select id, username, age, gender, phone, delete_flag, create_time,
update_time from userinfo where username like '%#{key}%' ")
List<UserInfo> queryAllUserByLike(String key);

把 #{} 改成 ${} 可以正确查出来,但是 ${} 存在SQL注⼊的问题,所以不能直接使⽤ ${}

解决方法:使⽤ mysql的内置函数concat()来处理,实现代码如下:

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

三、动态SQL

1.1 <if>标签

<if>标签的作用:动态拼接

XML 复制代码
<insert id="insertUserByCondition">
    insert into userinfo (
    username,
    `password`,
    age,
    <if test="gender != null">
        gender,
    </if>
    phone)
    values (
    #{username},
    #{age},
    <if test="gender != null">
        #{gender},
    </if>
    #{phone})
</insert>

上述代码:如果gender不为空,则会将其拼接到SQL语句中(也就是我们在传参时,传了gender这个参数)

1.2 <trim>标签

<trim>标签的作用:添加或删除前缀和后缀

刚才我们只有一个选填字段,事实上可能有多个:

XML 复制代码
<insert id="insertUserByCondition">
        INSERT INTO userinfo
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="username !=null">
                username,
            </if>
            <if test="password !=null">
               `password`,
            </if>
            <if test="age != null">
                age,
            </if>
            <if test="gender != null">
                gender,
            </if>
            <if test="phone != null">
                phone,
            </if>
        </trim>
        VALUES
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="username !=null">
                #{username},
            </if>
            <if test="password !=null">
                #{password},
            </if>
            <if test="age != null">
                #{age},
            </if>
            <if test="gender != null">
                #{gender},
            </if>
            <if test="phone != null">
                #{phone}
            </if>
        </trim>
</insert>

trim标签中:

  • prefix:以prefix的值作为整个语句块的前缀
  • suffix:以suffix的值作为整个语句块的后缀
  • prefixOverrides:表示整个语句块要去除的前缀
  • suffixOverrides:表示整个语句块要去除的后缀,在上述代码中最后拼接的字段可能结尾带有逗号,所以加上suffixOverrides

1.3 <where>标签

看下图,有时条件也需要动态拼接:

<where>标签的主要作用:动态拼接条件

XML 复制代码
<select id="queryByCondition" resultType="com.example.demo.model.UserInfo">
        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>
</select>

<where>标签还有两个作用:

  1. 如果没有判断条件,where会自动去除
  2. 如果第一个条件有前缀and或or,<where>标签也会自动去除

1.4 <set>标签

<set>标签的作用:动态指定更新的内容

XML 复制代码
<update id="updateUserByCondition">
        update userinfo
        <set>
            <if test="username != null">
                username = #{username},
            </if>
            <if test="age != null">
                age = #{age},
            </if>
            <if test="deleteFlag != null">
                delete_flag = #{deleteFlag},
            </if>
        </set>
        where id = #{id}
</update>

<set>标签可以自动删除额外的逗号

1.5 <foreach>标签

<foreach>标签的作用:对集合进行遍历

批量删除:

java 复制代码
Integer deleteByIds(List<Integer> ids);
XML 复制代码
<delete id="deleteByIds">
    delete from userinfo
    where id in
    <foreach collection="ids" item="id" separator="," open="(" close=")">
        #{id}
    </foreach>
</delete>
  • collection:绑定方法参数中的集合,也就是要遍历的集合
  • item:遍历的每一个对象
  • separator:每次遍历之间间隔的字符串
  • open:整个语句块开头的字符串
  • close:整个语句块结尾的字符串

1.6 <include>标签

在xml文件中配置的SQL有许多重复的片段

解决方法:将重复的sql片段提取出来放在<sql>标签,然后通过<include>标签复用

XML 复制代码
<sql id="allColumn">
    username, password, age, gender, phone
</sql>
XML 复制代码
<select id="selectUserById" resultType="com.example.demo.model.UserInfo">
        select
        <include refid="allColumn"></include>
        from userinfo where id = ${id}
</select>

🙉本篇文章到此结束

相关推荐
苏-言4 小时前
SSM框架探秘:Spring 整合 Mybatis 框架
java·spring·mybatis
所待.3837 小时前
锁升级过程与优化操作
java·jvm·java-ee
专职8 小时前
spring boot中使用spring-security案例
spring boot·后端·spring
打破砂锅问到底0078 小时前
技术周总结 01.13~01.19 周日(Spring Visual Studio git)
git·spring·visual studio
HYUJKI10 小时前
自定义注解
java·开发语言·spring
康惠桀13 小时前
Mybatis-plus缓存
缓存·mybatis
我要学编程(ಥ_ಥ)2 天前
初始JavaEE篇 —— Spring Web MVC入门(上)
spring boot·spring·java-ee·mvc
码农幻想梦2 天前
实验七 带函数查询和综合查询(2)
数据库·sql·mybatis
码农小灰2 天前
Spring MVC中HandlerInterceptor的作用及应用场景
java·spring boot·后端·spring·mvc