Mybatis 注解开发 + 动态SQL

     阅读:23

Hello 大家好我是橙子同学,今天分享注解Mybatis注解开发+动态sql

目录

每文一铺垫(今天有小插曲哦)

注解开发

添加 @Insert

删除 @Delete

查询 @Select

修改 @Update

         实现结果集封装  @Result

        实现一对一结果集封装 @one

        实现多对多结果集封装 @Many  

动态SQL

        标签 <set>  <if>

        标签<where>

        标签<foreach>

        标签<choose>

        标签 <when>

收尾


每文一铺垫(今天有小插曲哦)

    先说一个小插曲,因为 橙子同学确实是快要找实习了,这几天宅在家就想着试试水,毕竟没接触过,也不知道这个圈子的包容性强不强,今天早晨可能没太睡醒,一冲动就给很多公司投递了简历(包括阿里和字节),因为有一个“一键投递”功能,所以我就点了,大概中午的时候接到了一个hr的电话,刚接到电话感觉这个人不太靠谱,因为他说话嗯啊的,还在打哈欠,每问一个问题之前要想好久,说好几个“就是……就是……”,感觉他比我紧张,传达给我的信息就是想要我独立开发一个小程序,前端+后端都是我完成,我的印象里这个东西不应该是分工合作的么,做前端的做页面,做后端的搞功能,这要是一个人做不会累死么(可能是我了解的不多),经过几分钟的聊天之后,他加了我的微信,然后发给了几张拼多多首页,然后一个电话过来,问我这个页面用代码怎么写,此时此刻小橙的内心已经很激动了,因为第一次遇见这样的,好像上来就面试一样,反正我就把我脑子里的东西尽量表达出来,最后的最后他说“好的,了解了,再见” 。不出意外——凉凉了。但是这次给我的感觉就是 hr能不能 睡醒了再沟通,都表达不清楚自己想要的是什么;另外我的技术有待提升,这个圈子是不会给菜鸟机会的,难过的一天……

好啦步入主题:注解开发+动态SQL

注解开发

     在之前的Mybatis基础开发操作的时候,我们的sql语句是写在映射文件里的,映射文件提供了“增、删、改、查”标签,然后将映射文件与接口连接,在测试类中调用接口中的方法,今天介绍的注解开发省去了在映射文件中的操作,让我们的代码更加清晰而且简洁。

添加 @Insert

直接在接口“脑袋上”添加注解@Insert,把SQL语句写在后面

补充:@Options 在添加属性的同时获取  属性值

    //添加
    @Insert("insert into tb_person values(null,#{name},#{age},#{sex})")
   @Options(useGeneratedKeys = true,keyProperty = "id",keyColumn = "id")
     void addPerson(Person person);

在测试类里测试一下

@Before 是指测试代码执行前先执行的内容

每个测试都需要读取配置文件;获取sqlSession工厂对象;创建dao接口的代理对象;所以我们把他们抽出来放在@Before里,就不需要每次都写啦~

@After   测试代码执行后,执行的内容

关闭操作 释放资源

public class MyTest {
    private SqlSession sqlSession ;
    private PersonMapper mapper;
    @Before
    public void before(){
        sqlSession = MyBatisUtils.getSqlSession();
        mapper = sqlSession.getMapper(PersonMapper.class);
    }
    @After
    public void after(){
        sqlSession.close();
    }


    @Test
    public void test1(){
        Person person = new Person();
        person.setName("李易峰");
        person.setAge(23);
        person.setSex("男");
        mapper.addPerson(person);
        System.out.println(person);
    }

}

“李易峰”就添加成功啦

删除 @Delete

    //删除
    @Delete("delete from tb_person where id=#{id}")
    void deleteById(Integer id);

查询 @Select

    //查询
    @Select("select * from tb_person where id=#{id}")
    Person findById(Integer id);

 修改 @Update

    //修改
    @Update("update tb_person set name=#{name},age=#{age},sex=#{sex} where id=#{id}")
    void updatePerson(Person person);

实现结果集封装  @Result

一对一关联查询

接口

public interface IdCardMapper {
    @Select("select * from idcard where id=#{id}")
    public IdCard findById(Integer id);
}

实现一对一结果集封装 @one

  @Results(id = "personAndCard",value = {
            @Result(id = true,property = "id",column = "id"),
            @Result(property = "name",column = "name"),
            @Result(property = "age",column = "age"),
            @Result(property = "idCard",column = "card_id",one = @One(select = "com.mapper.IdCardMapper.findById"))
    })
    @Select("select * from person where id=#{id}")
    Person findById(Integer id);

实现多对多结果集封装 @Many  

接口

public interface OrderMapper {
    @Select("select * from tb_order where user_id=#{uid}")
    List<Order> findByUserId(Integer uid);
}
public interface UserMapper {
    @Results(id = "userAndOrder",value = {
            @Result(id = true,property = "id",column = "t_id"),
            @Result(property = "name",column = "t_name"),
            @Result(property = "age",column = "t_age"),
            @Result(property = "orders",column = "t_id",
                    many = @Many(select = "com.mapper.OrderMapper.findByUserId"))
    })
    @Select("select * from tb_user where t_id=#{id}")
    User findById(Integer id);
}

 

      增删改查 关联查询 都实现啦,但是有没有注意到,有的部分很麻烦,比如在增加、修改,需要更新数据的时候,需要把所有的字段都修改,很不方便,橙子只想修改年龄,但是“姓名”“性别”“ID”……都需要传进来修改,很麻烦,字段少的情况下,可以,忍忍就过去了,十几二十几个字段那岂不是太头痛了,所以接下来介绍解决这个问题的方法:动态SQL

动态SQL

    动态sql的理念很简单,“哪里不会点哪里~”简单来说就是需要哪个字段 诶,咱就去拼接哪个字段,不用的就不管啦,简单介绍一下动态sql标签。

标签<set>  <if>

大家对于<if>标签肯定不陌生,很容易理解,条件判断嘛,<set> 修改  举个栗子:

如果name不为null ,筛选用户名 ;

如果gender不为null ,筛选性别 ;

如果age不为null ,筛选年龄;

如果……

 标签<where>

结合之前的sql思考,可知这个标签,就是拼接筛选条件,举个栗子:

如果name不为null ,筛选用户名 ;

如果gender不为null ,筛选性别 ;

如果age不为null ,筛选年龄;

如果……

标签<foreach >

与JavaScript中的foreach类似,进行遍历操作

属性如下

   collection:代表要遍历的集合元素,注意编写时不要写#{}
    open:代表语句的开始部分
    close:代表结束部分
    item:代表遍历集合的每个元素,生成的变量名
    sperator:代表分隔符

举个栗子:

<!--根据多个id查询用户信息-->
<select id="findUsersByIds" resultType="user" >
    SELECT *from USER
    <where>
        <foreach collection="array"  open="and id in (" close=")" separator="," item="uid">
            #{uid}
        </foreach>
    </where>
</select>

标签<choose>

 此标签解释来源:https://www.jianshu.com/p/9f97543b6b2e

  有时候我们并不想应用所有的条件,而只是想从多个选项中选择一个。而使用if标签时,只要test中的表达式为 true,就会执行 if 标签中的条件。MyBatis 提供了 choose 元素。if标签是与(and)的关系,而 choose 是或(or)的关系。

choose标签是按顺序判断其内部when标签中的test条件出否成立,如果有一个成立,则 choose 结束。当 choose 中所有 when 的条件都不满则时,则执行 otherwise 中的sql。类似于Java 的 switch 语句,choose 为 switch,when 为 case,otherwise 则为 default。

标签<when> 

类似于 switch ,按照已经筛选好的条件,当 when 中有条件满足的时候,就会执行 choose,当所有的条件都不满足的时候就执行 otherwise

注解中可以使用动态sql么?可以,当然可以。

用添加字段  举个栗子

 @Update("<script>" +
            "update tb_person " +
            "<set>" +
            "<if test='name!=null'>" +
            "name=#{name}," +
            "</if>" +
            "<if test='age!=null'>" +
            "age=#{age}," +
            "</if>" +
            "<if test='sex!=null'>" +
            "sex=#{sex}" +
            "</if>" +
            "</set>" +
            "where id=#{id}" +
            "</script>")
    void updatePerson2(Person person);

 哇,头痛,没有提示,简直是手撕sql啊,但凡有一个符号写错了,直接报错,还找不到,还有比这更闹心的么?橙子要说了,还不如用映射文件呢,对啊,那么这个地方,记笔记,可以使用注解+映射文件结合。

在映射文件里面写动态sql

<?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文件所在路径 -->
<mapper namespace="com.mapper.PersonMapper">
    <update id="updatePerson3" parameterType="Person" >
        update tb_person
        <set>
            <if test="name!=null">
                name=#{name},
            </if>
            <if test="age!=null">
                age=#{age},
            </if>
            <if test="sex!=null">
                sex=#{sex}
            </if>
        </set>
        where id=#{id}
    </update>

</mapper>

接口里和以前一样

void updatePerson3(Person person);

收尾

    其实对于动态SQL中的有些标签,我理解的也有些模糊,所以可能有的地方写的不是太清楚,欢迎大家指正,包括在写的过程中我也去查询了其他人是怎么写的,但是主要还是来源于上课老师大大传授给我的,有部分内容也引用了老师的, 跪求我的主讲老师不会刷到我的博客哈哈哈哈,

    上期说这期还有一级缓存,二级缓存和和延迟加载, 写完这些我发现太多了,那就继续再往后推一推吧~~

   趁着小橙还没火,还不赶紧关注 吼吼吼吼~~