zoukankan      html  css  js  c++  java
  • Spring Boot入门系列(十九)整合mybatis,使用注解实现动态Sql、参数传递等常用操作!

    前面介绍了Spring Boot 整合mybatis 使用注解的方式实现数据库操作,介绍了如何自动生成注解版的mapper 和pojo类。 接下来介绍使用mybatis 常用注解以及如何传参数等数据库操作中的常用操作。

    其实,mybatis 注解方式 和 XML配置方式两者的使用基本上相同,只有在构建 SQL 脚本有所区别,所以这里重点介绍两者之间的差异,以及增删改查,参数传递等注解的常用操作。

    Spring Boot 整合mybatis 使用xml配置版之前已经介绍过了,不清楚的朋友可以看看之前的文章:https://www.cnblogs.com/zhangweizhong/category/1657780.html

    注解介绍

    mybatis 注解方式的最大特点就是取消了 Mapper 的 XML 配置,具体的 SQL 脚本直接写在 Mapper 类或是 SQLProvider 中的方法动态生成 
    mybatis 提供的常用注解有: @Insert 、@Update 、@Select、 @Delete 等标签,这些注解其实就是 MyBatis 提供的来取代其 XML配置文件的。

    1、@Select 注解

    @Select,主要在查询的时候使用,查询类的注解,一般简单的查询可以使用这个注解。

    @Select({
    "select",
    "id, company_id, username, password, nickname, age, sex, job, face_image, province, ",
    "city, district, address, auth_salt, last_login_ip, last_login_time, is_delete, ",
    "regist_time",
    "from sys_user",
    "where id = #{id,jdbcType=VARCHAR}"
    })
    @Results({
    @Result(column="id", property="id", jdbcType=JdbcType.VARCHAR, id=true),
    @Result(column="company_id", property="companyId", jdbcType=JdbcType.VARCHAR),
    @Result(column="face_image", property="faceImage", jdbcType=JdbcType.VARCHAR),
    @Result(column="auth_salt", property="authSalt", jdbcType=JdbcType.VARCHAR),
    @Result(column="last_login_ip", property="lastLoginIp", jdbcType=JdbcType.VARCHAR),
    @Result(column="last_login_time", property="lastLoginTime", jdbcType=JdbcType.TIMESTAMP),
    @Result(column="is_delete", property="isDelete", jdbcType=JdbcType.INTEGER),
    @Result(column="regist_time", property="registTime", jdbcType=JdbcType.TIMESTAMP)
    })
    User selectByPrimaryKey(String id);
    
    

    注意:如果是多个参数,需要将 #后面的参数和传入的变量名保持一致。

    2、@Insert 注解

    @Insert,插入数据时使用,直接传入数据实体类,mybatis 会属性自动解析到对应的参数。所以需要将 #后面的参数和实体类属性保持一致。

        @Insert({
            "insert into sys_user (id, company_id, ",
            "username, password, ",
            "nickname, age, sex, ",
            "job, face_image, ",
            "province, city, ",
            "district, address, ",
            "auth_salt, last_login_ip, ",
            "last_login_time, is_delete, ",
            "regist_time)",
            "values (#{id,jdbcType=VARCHAR}, #{companyId,jdbcType=VARCHAR}, ",
            "#{username,jdbcType=VARCHAR}, #{password,jdbcType=VARCHAR}, ",
            "#{nickname,jdbcType=VARCHAR}, #{age,jdbcType=INTEGER}, #{sex,jdbcType=INTEGER}, ",
            "#{job,jdbcType=INTEGER}, #{faceImage,jdbcType=VARCHAR}, ",
            "#{province,jdbcType=VARCHAR}, #{city,jdbcType=VARCHAR}, ",
            "#{district,jdbcType=VARCHAR}, #{address,jdbcType=VARCHAR}, ",
            "#{authSalt,jdbcType=VARCHAR}, #{lastLoginIp,jdbcType=VARCHAR}, ",
            "#{lastLoginTime,jdbcType=TIMESTAMP}, #{isDelete,jdbcType=INTEGER}, ",
            "#{registTime,jdbcType=TIMESTAMP})"
        })
        int insert(User record);

    注意:需要将 #后面的参数和实体类属性保持一致。

     

    3、@Update 注解

    @Update,一般数据更新操作可以使用 @Update注解实现。

    @Update({
            "update sys_user",
            "set company_id = #{companyId,jdbcType=VARCHAR},",
              "username = #{username,jdbcType=VARCHAR},",
              "password = #{password,jdbcType=VARCHAR},",
              "nickname = #{nickname,jdbcType=VARCHAR},",
              "age = #{age,jdbcType=INTEGER},",
              "sex = #{sex,jdbcType=INTEGER},",
              "job = #{job,jdbcType=INTEGER},",
              "face_image = #{faceImage,jdbcType=VARCHAR},",
              "province = #{province,jdbcType=VARCHAR},",
              "city = #{city,jdbcType=VARCHAR},",
              "district = #{district,jdbcType=VARCHAR},",
              "address = #{address,jdbcType=VARCHAR},",
              "auth_salt = #{authSalt,jdbcType=VARCHAR},",
              "last_login_ip = #{lastLoginIp,jdbcType=VARCHAR},",
              "last_login_time = #{lastLoginTime,jdbcType=TIMESTAMP},",
              "is_delete = #{isDelete,jdbcType=INTEGER},",
              "regist_time = #{registTime,jdbcType=TIMESTAMP}",
            "where id = #{id,jdbcType=VARCHAR}"
        })
        int updateByPrimaryKey(User record);

    4、@Delete 注解
    @Delete 数据删除的注解

        @Delete({
            "delete from sys_user",
            "where id = #{id,jdbcType=VARCHAR}"
        })
        int deleteByPrimaryKey(String id);

    5、@Results 和 @Result 注解 

    @Results 和 @Result 主要作用是,当有一些特殊的场景需要处理,查询的返回结果与期望的数据格式不一致时,可以将将数据库中查询到的数值自动转化为具体的属性或类型,,修饰返回的结果集。比如查询的对象返回值属性名和字段名不一致,或者对象的属性中使用了枚举等。如果实体类属性和数据库属性名保持一致,就不需要这个属性来修饰。

    @Select({
        "select",
        "id, company_id, username, password, nickname, age, sex, job, face_image, province, ",
        "city, district, address, auth_salt, last_login_ip, last_login_time, is_delete, ",
        "regist_time",
        "from sys_user",
        "where id = #{id,jdbcType=VARCHAR}"
    })
    @Results({
        @Result(column="id", property="id", jdbcType=JdbcType.VARCHAR, id=true),
        @Result(column="company_id", property="companyId", jdbcType=JdbcType.VARCHAR),
        @Result(column="face_image", property="faceImage", jdbcType=JdbcType.VARCHAR),
        @Result(column="auth_salt", property="authSalt", jdbcType=JdbcType.VARCHAR),
        @Result(column="last_login_ip", property="lastLoginIp", jdbcType=JdbcType.VARCHAR),
        @Result(column="last_login_time", property="lastLoginTime", jdbcType=JdbcType.TIMESTAMP),
        @Result(column="is_delete", property="isDelete", jdbcType=JdbcType.INTEGER),
        @Result(column="regist_time", property="registTime", jdbcType=JdbcType.TIMESTAMP)
    })
    User selectByPrimaryKey(String id);

    上面的例子可以看到,数据库中的company_id 字段和实体类中定义的 companyId 属性的名称不一致,需要Result 转换。

    以上就是项目中常用的增、删、改、查的操作, 其实这些在基本的方法不需要手动写,用前面讲过的mybatis generator 自动生成即可。讲这些主要是熟悉这些常用的注解。

    传参方式

    上面介绍了mybatis 常用的注解,如何实现增删改查的操作,相信很多人会有疑问了: mybatis 是如何将参数传递到 SQL 中的呢,都有哪几种传参方式呢? 下面就来一一介绍mybatis 注解版的传参方式。

    1、直接传参

    对于单个参数的方法,可直接使用 #{id} 的方式接收同名的变量参数。

        @Delete("delete from sys_user where id = #{id,jdbcType=VARCHAR}")
        int deleteByPrimaryKey(String id);

     

    2、使用 @Param 注解

    @Param注解的作用是给参数命名,参数命名后就能根据名字得到参数值,正确的将参数传入sql语句中 。如果你的方法有多个参数,@Param 注解 会在方法的参数上就能为它们取自定义名字,参数则先以 "param" 作前缀,再加上它们的参数位置作为参数别名。例如, #{param1}、 #{param2},这个是默认值。如果注解是 @Param("person"),那么参数就会被命名为 #{person}。

    @Select("SELECT * FROM sys_user WHERE username = #{username} and password = #{password}")
    List<User> getListByUserSex(@Param("username") String userName, @Param("password") String password);
    
    // 不自定义param 时,默认使用 param + 参数序号 或者 0,1,值就是参数的值。
    @Select("SELECT * FROM sys_user WHERE username = #{param1} and password = #{param2}")
    List<User> getListByUserSex(String userName, String password);

    3、Map 传值 
    需要传送多个参数时,也可以考虑使用 Map的形式。

    @Select("SELECT * FROM sys_user WHERE username=#{username} AND password = #{password}")
    List<User> getListByNameAndSex(Map<String, Object> map);

    调用时将参数依次加入到 Map 中即可。

    Map param= new HashMap();
    param.put("username","admin");
    param.put("password","123456");
    List<User> users = userMapper.getListByNameAndSex(param)

    4、使用pojo对象
    使用pojo对象传参是比较常用的传参方式。像上面的insert、update 等方法。都是直接传入user对象。

    @Update({
        "update sys_user",
        "set company_id = #{companyId,jdbcType=VARCHAR},",
          "username = #{username,jdbcType=VARCHAR},",
          "password = #{password,jdbcType=VARCHAR},",
          "nickname = #{nickname,jdbcType=VARCHAR},",
          "age = #{age,jdbcType=INTEGER},",
          "sex = #{sex,jdbcType=INTEGER},",
          "job = #{job,jdbcType=INTEGER},",
          "face_image = #{faceImage,jdbcType=VARCHAR},",
          "province = #{province,jdbcType=VARCHAR},",
          "city = #{city,jdbcType=VARCHAR},",
          "district = #{district,jdbcType=VARCHAR},",
          "address = #{address,jdbcType=VARCHAR},",
          "auth_salt = #{authSalt,jdbcType=VARCHAR},",
          "last_login_ip = #{lastLoginIp,jdbcType=VARCHAR},",
          "last_login_time = #{lastLoginTime,jdbcType=TIMESTAMP},",
          "is_delete = #{isDelete,jdbcType=INTEGER},",
          "regist_time = #{registTime,jdbcType=TIMESTAMP}",
        "where id = #{id,jdbcType=VARCHAR}"
    })
    int updateByPrimaryKey(User record);


    以上,就是Mybatis 传参的四种方式。根据方法的参数选择合适的传值方式。

    动态 SQL

    实际项目中,除了使用一些常用的增删改查的方法之外,有些复杂的需求,可能还需要执行一些自定义的动态sql。mybatis 除了提供了@Insert、@Delete 这些常用的注解,还提供了多个注解如:@InsertProvider,@UpdateProvider,@DeleteProvider和@SelectProvider,用来建立动态sql 和让 mybatis 执行这些sql 的注解。下面就来实现按字段更新的功能。

    1、首先在 UserSqlProvider 中创建 拼接sql的方法。

    public String updateByPrimaryKeySelective(User record) {
            BEGIN();
            UPDATE("sys_user");
            
            if (record.getCompanyId() != null) {
                SET("company_id = #{companyId,jdbcType=VARCHAR}");
            }
            
            if (record.getUsername() != null) {
                SET("username = #{username,jdbcType=VARCHAR}");
            }
            
            if (record.getPassword() != null) {
                SET("password = #{password,jdbcType=VARCHAR}");
            }
            
            if (record.getNickname() != null) {
                SET("nickname = #{nickname,jdbcType=VARCHAR}");
            }
            
            if (record.getAge() != null) {
                SET("age = #{age,jdbcType=INTEGER}");
            }
            
            if (record.getSex() != null) {
                SET("sex = #{sex,jdbcType=INTEGER}");
            }
            
            if (record.getJob() != null) {
                SET("job = #{job,jdbcType=INTEGER}");
            }
            
            if (record.getFaceImage() != null) {
                SET("face_image = #{faceImage,jdbcType=VARCHAR}");
            }
            
            if (record.getProvince() != null) {
                SET("province = #{province,jdbcType=VARCHAR}");
            }
            
            if (record.getCity() != null) {
                SET("city = #{city,jdbcType=VARCHAR}");
            }
            
            if (record.getDistrict() != null) {
                SET("district = #{district,jdbcType=VARCHAR}");
            }
            
            if (record.getAddress() != null) {
                SET("address = #{address,jdbcType=VARCHAR}");
            }
            
            if (record.getAuthSalt() != null) {
                SET("auth_salt = #{authSalt,jdbcType=VARCHAR}");
            }
            
            if (record.getLastLoginIp() != null) {
                SET("last_login_ip = #{lastLoginIp,jdbcType=VARCHAR}");
            }
            
            if (record.getLastLoginTime() != null) {
                SET("last_login_time = #{lastLoginTime,jdbcType=TIMESTAMP}");
            }
            
            if (record.getIsDelete() != null) {
                SET("is_delete = #{isDelete,jdbcType=INTEGER}");
            }
            
            if (record.getRegistTime() != null) {
                SET("regist_time = #{registTime,jdbcType=TIMESTAMP}");
            }
            
            WHERE("id = #{id,jdbcType=VARCHAR}");
            
            return SQL();
        }

    2、Mapper 中引入 updateByPrimaryKeySelective 方法

        @UpdateProvider(type=UserSqlProvider.class, method="updateByPrimaryKeySelective")
        int updateByPrimaryKeySelective(User record);

    说明:

      type:动态生成 SQL 的类。

      method:类中具体的方法名。

    以上,就是使用sqlprovider 动态创建sql,除了示例中的 @UpdateProvider ,,还有 @InsertProvider、 @SelectProvider @DeleteProvider 提供给插入、查询、删除的时使用。 

    最后

    上面,介绍了使用mybatis 常用注解实现增、删、改、查。以及mybatis 常用的四种参数传递方式。

    这个系列课程的完整源码,也会提供给大家。大家关注我的微信公众号(架构师精进),回复:springboot源码。获取这个系列课程的完整源码。

  • 相关阅读:
    archlinux .bash_history
    Ubuntu环境下挂载新硬盘
    软碟通 UltraISO U启替代品 Win32DiskImager 无设备 无盘符 无u盘 无优盘 解决方案 之diskpart
    delphi Integer overflow
    MSBuild Tools offline
    delphi synedit免费的拼写检查器dll
    git 自定义命令行
    lua编译
    gcc ar
    Windows Subsystem for Linux (WSL)挂载移动硬盘U盘 卸载 c d 盘
  • 原文地址:https://www.cnblogs.com/zhangweizhong/p/13118410.html
Copyright © 2011-2022 走看看