美文网首页Mysql
Mybatis实践笔记-去XML化的注解开发

Mybatis实践笔记-去XML化的注解开发

作者: 叶子的翅膀 | 来源:发表于2020-09-28 15:16 被阅读0次

    文章内容输出来源:拉勾教育Java高薪训练营

    介绍

    Mybatis使用注解开发,可以减少编写XML文件,对于不复杂的数据逻辑处理也是比较简单适用。
    本文演示Mybatis使用注解开发的增删改查操作。

    注解介绍

    • @Insert:插入

    • @Update:更新

    • @Delete:删除

    • @Select:查询

    • @Result:封装结果集。对应xml文件中的<resultMap>中的<result>子标签

      • id:是否主键字段
      • column:数据库列名
      • property:属性名
      • one:一对一@One注解
      • many:一对多@Many注解

      如果列和属性的名称一样,则可以省略@result,mybatis会自动映射

    • @Results:多个封装结果集,与@Result一起使用。对应xml文件中的<resultMap>标签

    • @ResultMap:引用映射结果集,减少冗余

      eg:@ResultMap(value="studentMap")。其中value值为@Results中定义的id属性

    • @One:一对一结果集封装。对应xml文件中的<association>标签

      • select:指定多表查询的mapper
      • fetchType:加载方式,会覆盖全局的配置参数lazyLoadingEnabled
      • column:关联的外键ID
      • property:属性名

      fetchType:FetchType.EAGER表示立即加载,FetchType.LAZY表示延迟加载
      eg:@Result(column=" ",property="",one=@One(select=""))

    • @Many:一对多结果集封装。对应xml文件中的<collection>标签

      • select:指定多表查询的mapper
      • fetchType:加载方式,会覆盖全局的配置参数lazyLoadingEnabled
      • column:关联的外键ID
      • property:属性名
      • javaType:属性的类型,一般为List.class

      eg:@Result(property="",column="",javaType=List.class,many=@Many(select=""))

    • @Options:这个注解对应映射语句中的属性配置。常用属性如下:

      • useCache=true,
      • flushCache=false,
      • resultSetType=FORWARD_ONLY,
      • statementType=PREPARED,
      • fetchSize= -1
      • timeout=-1 ,
      • useGeneratedKeys=false
      • keyProperty="id"
    • @Param:参数注解

      当需要多个参数时,此注解用于给每一个参数定义名称。否则就会被以它们的顺序位置命名,如#{1}、#{2}等。
      使用@Param(“person”),SQL中参数解析就可以使用#{person}

    • @SelectKey:插入后,获取id的值

      eg:@SelectKey(statement = "select last_insert_id()" ,keyProperty = "id",keyColumn = "id",resultType = int.class,before = false)
      其中before属性,默认是true,在执行插入语句之前,执行select last_insert_id()。如果设置为flase,则在插入这个语句之后,执行select last_insert_id()
      在已经被@Insert/@InsertProvider/@Update/@UpdateProvider注解了的方法上使用才有效

    • @InsertProvider、@DeleteProvider、@UpdateProvider、@SelectProvider:用于生成插入、删除、更新、查询的SQL语句

      eg:@SelectProvider(type = SqlProvider.class, method = "selectUser")

    示例

    一、开始之前的配置

    项目代码链接:mybatis_demo_01_annoation

    1、基于order订单表和user表的操作,两张表的实体如下

    • OrderEntity
    public class OrderEntity {
        private Integer id;
        private Integer userId;
        private BigDecimal amount;
        //订单关联的用户
        private UserEntity user;
        //ignore setter/getter
    }
    
    • UserEntity
    public class UserEntity {
        private Integer id;
        private String name;
        //用户关联的订单数据
        private List<OrderEntity> orders;
        //ignore setter/getter
    }    
    

    2、创建OrderDao和UserDao接口

    3、在mybatis配置文件上配置对应的mapper,或者直接配置mapper所在的package包路径

    <configuration>
        <mappers>
            <!--<mapper class="com.yyh.demo.dao.OrderDao"/>
            <mapper class="com.yyh.demo.dao.UserDao"/>-->
            <package name="com.yyh.demo.dao"/>
        </mappers>
    </configuration>
    

    4、创建OrderTest和UserTest的单元测试类

    二、新增订单数据

    • 多参数新增订单
    /**
      * 多参数添加订单数据
      * @param userId 用户ID
      * @param amount 金额
      * @return 返回值大于0表示插入成功
      */
    @Insert("INSERT INTO `order`(user_id, amount) VALUES(#{userId}, #{amount})")
    int insert(@Param("userId") Integer userId, @Param("amount") BigDecimal amount);
    
    • 实体参数新增订单
    /**
        * 实体参数添加订单数据
        * @param order 订单实体
        * @return 返回值大于0表示插入成功
        */
    @Insert("INSERT INTO `order`(user_id, amount) VALUES(#{order.userId}, #{order.amount})")
    int insertWithEntity(@Param("order") OrderEntity order);
    
    • 实体参数新增订单,并返回新增的订单ID
    /**
        * 实体参数添加订单数据,并返回订单ID
        * @param order 订单实体
        * @return 返回值大于0表示插入成功
        */
    @Insert("INSERT INTO `order`(user_id, amount) VALUES(#{order.userId}, #{order.amount})")
    @Options(useGeneratedKeys = true, keyProperty = "order.id", keyColumn = "id")
    int insertWithEntityAndReturnId(@Param("order") OrderEntity order);
    

    三、更新订单数据

    • 多参数更新订单金额
    /**
        * 更新某订单的金额
        * @param id 订单ID
        * @param amount 金额
        * @return 返回值大于0表示更新成功
        */
    @Update("UPDATE `order` SET amount=#{amount} WHERE id=#{id}")
    int updateAmount(@Param("id") Integer id, @Param("amount") BigDecimal amount);
    
    • 实体参数更新订单金额
    /**
        * 更新某订单的金额
        * @param order 订单实体
        * @return 返回值大于0表示更新成功
        */
    @Update("UPDATE `order` SET amount=#{order.amount} WHERE id=#{order.id}")
    int updateAmountWithEntity(@Param("order") OrderEntity order);
    

    四、删除订单数据

    /**
        * 根据订单ID删除订单
        * @param id 订单ID
        * @return 返回值大于0表示删除成功
        */
    @Delete("DELETE FROM `order` WHERE id=#{id}")
    int delete(@Param("id") Integer id);
    

    五、查询全部订单数据

    @Select("SELECT * FROM `order`")
    List<OrderEntity> selectList();
    

    六、查询单条订单数据

    /**
        * 根据订单ID查询订单数据
        * @param id 订单ID
        * @return
        */
    @Select("SELECT * FROM `order` WHERE id=#{id}")
    OrderEntity selectOne(@Param("id") Integer id);
    

    七、查询订单以及关联的用户数据

    • 联合查询
    /**
        * 获取订单数据以及关联的用户信息
        * @param id 订单ID
        * @return
        */
    @Select("SELECT t1.id,t1.amount,t1.user_id,t2.name as user_name FROM `order` t1,user t2 where t1.user_id=t2.id AND t1.id=#{id}")
    @Results({
            @Result(id=true, column = "id", property = "id"),
            @Result(column = "amount", property = "amount"),
            @Result(column = "user_id", property = "userId"),
            @Result(column = "user_id", property = "user.id"),
            @Result(column = "user_name", property = "user.name")
    })
    OrderEntity selectOneWithUser(Integer id);
    
    • 嵌套查询
    /**
        * 获取订单数据以及关联的用户信息
        * @param id 订单ID
        * @return
        */
    @Select("SELECT * FROM `order` WHERE id=#{id}")
    @Results({
            @Result(id=true, column = "id", property = "id"),
            @Result(column = "amount", property = "amount"),
            @Result(column = "user_id", property = "user",
                    javaType = UserEntity.class, one = @One(select = "com.yyh.demo.dao.UserDao.selectOne"))
    })
    OrderEntity selectOneWithUser2(Integer id);
    

    八、查询用户以及关联的订单数据

    • 嵌套查询,延迟加载
    /**
        * 获取某用户的数据以及关联订单数据。延迟加载
        * @param id
        * @return
        */
    @Select("select * from user where id=#{id}")
    @Results({
            @Result(id=true, column = "id", property = "id"),
            @Result(column = "name", property = "name"),
            @Result(property = "orders", column = "id",
                    javaType = List.class, many = @Many(select = "com.yyh.demo.dao.OrderDao.selectListByUser", fetchType = FetchType.LAZY))
    })
    UserEntity selectOneWithOrders(Integer id);
    
    • 嵌套查询
    /**
        * 获取某用户的数据以及关联订单数据
        * @param id
        * @return
        */
    @Select("select * from user where id=#{id}")
    @Results({
            @Result(id=true, column = "id", property = "id"),
            @Result(column = "name", property = "name"),
            @Result(property = "orders", column = "id",
                    javaType = List.class, many = @Many(select = "com.yyh.demo.dao.OrderDao.selectListByUser"))
    
    })
    UserEntity selectOneWithOrders2(Integer id);
    

    九、使用动态SQL支持复杂条件的查询订单数据

    • 用script标签包裹,像xml文件编写脚本
    public class OrderParam {
        //最小金额
        private BigDecimal minAmount;
        //最大金额
        private BigDecimal maxAmount;
        //用户ID
        private Integer userId;
        //ignore getter/setter
    }   
    
    /**
        * 复杂的查询订单数据
        * @param param
        * @return
        */
    @Select({
            "<script>",
            "SELECT * FROM `order`",
            "<where> ",
            "<if test='null != userId'>and user_id=#{userId}</if>",
            "<if test='null != minAmount'>and amount &gt;= #{minAmount}</if>",
            "<if test='null != maxAmount'>and amount &lt;= #{maxAmount}</if>",
            "</where>",
            "</script>"
    })
    List<OrderEntity> selectListByCondition2(OrderParam param);
    
    • 用Provider去实现SQL拼接
    1. 示例1
    public class OrderProvider {
    
        public String selectListByCondition(OrderParam param) {
            SQL sql = new SQL().SELECT("*").FROM("`order`");
            if(null != param.getUserId()) {
                sql.WHERE("user_id=#{userId}");
            }
            if(null != param.getMinAmount()) {
                sql.WHERE("amount>=#{minAmount}");
            }
            if(null != param.getMaxAmount()) {
                sql.WHERE("amount<=#{maxAmount}");
            }
            return sql.toString();
        }
    }
    
     /**
        * 复杂的查询订单数据
        * @param param
        * @return
        */
    @SelectProvider(type = OrderProvider.class, method="selectListByCondition")
    List<OrderEntity> selectListByCondition(OrderParam param);
    
    1. 示例2
    public class OrderProvider {
        public String selectListByCondition2(Map<String, Object> param) {
            SQL sql = new SQL().SELECT("*").FROM("`order`");
            if(null != param.get("userId")) {
                sql.WHERE("user_id=#{userId}");
            }
            if(null != param.get("minAmount")) {
                sql.WHERE("amount>=#{minAmount}");
            }
            if(null != param.get("maxAmount")) {
                sql.WHERE("amount<=#{maxAmount}");
            }
            return sql.toString();
        }
    }
    
    /**
        * 复杂的查询订单数据
        * @param userId 用户ID
        * @param minAmount 最小金额
        * @param maxAmount 最大金额
        * @return
        */
    @SelectProvider(type = OrderProvider.class, method="selectListByCondition2")
    List<OrderEntity> selectListByCondition3(@Param("userId") Integer userId, @Param("minAmount") BigDecimal minAmount, @Param("maxAmount") BigDecimal maxAmount);
    

    如果接口有多个参数,在provider中要使用Map<String, Object>来进行接收

    相关文章

      网友评论

        本文标题:Mybatis实践笔记-去XML化的注解开发

        本文链接:https://www.haomeiwen.com/subject/iziduktx.html