• 【Day 9】Mybatis CURD + XML 映射 + 动态 SQL


    1 Mybatis 基础操作

    下面进行:增删改查——C(create)U(update)R(retrieve)D(delete)

    1.1 删除(删)

    根据主键 id 进行删除

    注意 占位符 #{ }

    返回值是删除的记录条数

    测试:

    可以在日志中看到 mybatis 具体的语句

    预编译 SQL 的优点:

    • 性能更高
    • 更安全(防止 SQL 注入)

            SQL 注入:是通过操作输入的数据来修改事先定义好的SQL语句,以达到执行代码对服务器进行攻击的方法

            1 等于 1 是true,所以结果是 16,即查到了所有人,但是是大于 0 的,系统判断登录成功,可以进入系统

    使用预编译 SQL:

    就是使用 占位符 #{ }

    Mybatis 占位符

    1.2 插入(增)

    在 Mapper 里面写 insert 接口方法

    注意:

    • emp 的字段采用驼峰命名,而数据库的 emp 表,是用下划线命名(这样更直观)所以在填写 values 的时候,需要看清楚
    • id 不用填写,id 是自增(increment)
    • password 也不用填写,password 是默认'123456'

    然后测试

    如果需要拿到插入的员工的主键:

    1. @Insert("insert into emp (username, name, gender, image, job, entrydate, dept_id, create_time, update_time)\n" +
    2. "values (#{username}, #{name}, #{gender}, #{image}, #{job}, #{entrydate}, #{deptId}, #{createTime}, now());")
    3. public int insert(Emp emp);

    1.3 更新(改)

    1. @Update("update emp set username=#{username}, name=#{name}, gender=#{gender}, image=#{image},job=#{job}," +
    2. "entrydate=#{entrydate},dept_id=#{deptId},update_time=#{updateTime} where id=#{id}")
    3. public void update(Emp emp);

    1.4 查询(查)

    1. @Select("select * from emp where id=#{id}")
    2. public Emp select(Integer id);

    但是注意看,后面三个是 null 值

    在数据库中查询,就不是 null 值

    是因为 Emp 类字段 和 数据库表属性 不一致

    解决方案一:起别名

    1. @Select("select id, username, password, name, gender, image, job, entrydate, dept_id deptId," +
    2. " create_time createTime, update_time updateTime from emp where id=#{id}")
    3. public Emp select(Integer id);

    解决方法二:手动封装

    1. // 解决方案二:通过 @Results,@Result 手动封装
    2. @Results({
    3. @Result(column = "dept_id",property = "deptId"),
    4. @Result(column = "create_time", property = "createTime"),
    5. @Result(column = "update_time",property = "updateTime")
    6. })
    7. @Select("select * from emp where id = #{id}")
    8. public Emp select(Integer id);

    解决方法三:开启 mybatis 的驼峰命名自动映射开关

    a_column         =>         aColumn

    开启之后,直接按原来的写:

    1. // 解决方案三:开启 mybatis 的驼峰命名自动映射开关
    2. @Select("select * from emp where id=#{id}")
    3. public Emp select(Integer id);

    以上三种方法都会得到正确字段:

    下面是条件查询:

    输入张,性别,入职日期,结果根据更新日期降序

    1. @Select("select * from emp where name like '%${name}%' and gender = #{gender} and entrydate between #{begin} " +
    2. "and #{end} order by update_time desc")
    3. public List selectByCondition(@Param("name") String name,
    4. @Param("gender") Short gender,
    5. @Param("begin") LocalDate begin,
    6. @Param("end") LocalDate end);

    注:

    • 要正确地映射,使用注解@Parm
    • 而且 name 是 ${name}

    另:由于 name 使用了 ${name},这不是预编译 SQL,会导致性能差,SQL 注入

    解决办法:

    使用 MySQL 自带的 concat 方法,进行字符串拼接

    2 XML 映射文件

    Mybatis 操作数据库有两种方法

    • 注解
    • XML 映射文件

     注意创建文件夹的名字

    XML 文件里面的配置

    1. "1.0" encoding="UTF-8" ?>
    2. mapper
    3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    5. <mapper namespace="com.example.mapper.EmpMapper">
    6. mapper>

    2.1 MybatisX

    IDEA 插件,用来简化 mybatis 

    2.2 到底用注解还是 XML

    3 动态 SQL(终于讲到这一点了)

            为什么说“终于讲到这一点了”,

            因为之前我就有个疑问,如果我只想查一下姓张的人,我不指定性别和入职日期,以前那个代码就查询不了:

    1. @Select("select * from emp where name like concat('%',#{name},'%') and gender = #{gender} and entrydate between #{begin} " +
    2. "and #{end} order by update_time desc")
    3. public List selectByCondition(@Param("name") String name,
    4. @Param("gender") Short gender,
    5. @Param("begin") LocalDate begin,
    6. @Param("end") LocalDate end);

    动态 SQL:随着用户的输入或外部条件的变化而变化的SQL语句,我们称为动态 SQL

    Mybatis 中有很多动态 SQL 标签

    3.1

    在 XML 里面去写

    注意:and 要在新的一行里面写,之前我在行尾写,那样不行

    1. <mapper namespace="com.example.mapper.EmpMapper">
    2. <select id="selectByCondition" resultType="com.example.pojo.Emp">
    3. select *
    4. from emp
    5. where
    6. <if test="name!=null">
    7. name like concat('%',#{name},'%')
    8. if>
    9. <if test="gender!=null">
    10. and gender = #{gender}
    11. if>
    12. <if test="begin!=null">
    13. <if test="end!=null">
    14. and entrydate between #{begin} and #{end}
    15. if>
    16. if>
    17. order by update_time desc
    18. select>
    19. mapper>

    这样就可以查到只姓张的人了

    注意:判断入职日期,也可以在中间用 and,就不用像我那样两层 if:

    1. <if test="begin!=null and end!=null">
    2. if>

    但是对于只输入性别,其他三个字段都为 null,又报错

    1. @Test
    2. public void testSelectGender(){
    3. List empList = empMapper.selectByCondition(null, (short) 1, null, null);
    4. empList.stream().forEach(System.out::println);
    5. }

    因为 name 为 null,在 XML 里面跳过name,直接到 gender,where 直接以 and 开头了,

    解决办法:把 where 改为 

    标签版的 where 可以自动去掉 and 或者 or,并且在条件都不成立的情况下去掉 where(真的智能)

    3.2 关于之前 update 的动态 SQL

    之前的 update 存在问题

    正常应该是传过来什么字段,就更新什么字段,没有就不变

    但是现在是没有字段的情况下,直接设置为 null

    解决:使用动态 SQL

    就不用注解了,把之前代码注释掉

    1. // 这段代码有问题,现在不用了,在 XML 重写了
    2. // @Update("update emp set username=#{username}, name=#{name}, gender=#{gender}, image=#{image},job=#{job}," +
    3. // "entrydate=#{entrydate},dept_id=#{deptId},update_time=#{updateTime} where id=#{id}")
    4. public void update(Emp emp);

    在 XML 里加 

    1. <update id="update"> # 更新不需要返回什么东西,所以没有属性 resultType
    2. update emp
    3. set
    4. <if test="username!=null">username=#{username}if>
    5. <if test="name!=null">,name=#{name}if>
    6. <if test="gender!=null">,gender=#{gender}if>
    7. <if test="image!=null">,image=#{image}if>
    8. <if test="job!=null">,job = #{job},if>
    9. <if test="entrydate!=null">,entrydate=#{entrydate}if>
    10. <if test="deptId!=null">,dept_id=#{deptId}if>
    11. <if test="createTime!=null">,create_time=#{createTime}if>
    12. <if test="updateTime!=null">,update_time = now()if>
    13. where id=#{id}
    14. update>

     这一次我们把第20个人,张测试,把他性别改成女,其他的字段不变:

     还是像上次一样,set 也有标签版本的

    用标签版本的 set 更好

    3.3

    批量删除:

     MySQL 语句:

    delete from emp where id in (18,19,20);

    现在是 Mybatis:

    EmpMapper 里面添加:

     然后alt + 回车在 XML 里面写

    1. <delete id="deleteByIds">
    2. delete from emp where id in
    3. <foreach collection="list" item="id" separator="," open="(" close=")">
    4. #{id}
    5. foreach>
    6. delete>

     测试(没有 17 是因为之前删除过)

    3.4

    这两个标签解决代码复用

  • 相关阅读:
    Node.js精进(6)——文件
    研究了11种实时聊天软件,我发现都具备这些功能…
    憾住了!“吃透”字节跳动面试,四轮技术面通过,成功拿到offer
    Java私活200元,完成JavaSwing学生成绩管理系统(三)
    面试中常问的SQL注入题
    QT中进程的创建
    哈希表的实现
    JVM(一):jvm中的数据结构(内存模型):Java Virtual Machine Specification Runtime Data Areas
    五 RPM方式Jenkins环境搭建
    【AI】推理引擎中的模型小型化问题
  • 原文地址:https://blog.csdn.net/Yudiannann/article/details/138150757