Mybatis實踐筆記-去XML化的注解開發(fā)

文章內(nèi)容輸出來源:拉勾教育Java高薪訓(xùn)練營

介紹

Mybatis使用注解開發(fā),可以減少編寫XML文件,對于不復(fù)雜的數(shù)據(jù)邏輯處理也是比較簡單適用。
本文演示Mybatis使用注解開發(fā)的增刪改查操作。

注解介紹

  • @Insert:插入

  • @Update:更新

  • @Delete:刪除

  • @Select:查詢

  • @Result:封裝結(jié)果集。對應(yīng)xml文件中的<resultMap>中的<result>子標簽

    • id:是否主鍵字段
    • column:數(shù)據(jù)庫列名
    • property:屬性名
    • one:一對一@One注解
    • many:一對多@Many注解

    如果列和屬性的名稱一樣,則可以省略@result,mybatis會自動映射

  • @Results:多個封裝結(jié)果集,與@Result一起使用。對應(yīng)xml文件中的<resultMap>標簽

  • @ResultMap:引用映射結(jié)果集,減少冗余

    eg:@ResultMap(value="studentMap")。其中value值為@Results中定義的id屬性

  • @One:一對一結(jié)果集封裝。對應(yīng)xml文件中的<association>標簽

    • select:指定多表查詢的mapper
    • fetchType:加載方式,會覆蓋全局的配置參數(shù)lazyLoadingEnabled
    • column:關(guān)聯(lián)的外鍵ID
    • property:屬性名

    fetchType:FetchType.EAGER表示立即加載,F(xiàn)etchType.LAZY表示延遲加載
    eg:@Result(column=" ",property="",one=@One(select=""))

  • @Many:一對多結(jié)果集封裝。對應(yīng)xml文件中的<collection>標簽

    • select:指定多表查詢的mapper
    • fetchType:加載方式,會覆蓋全局的配置參數(shù)lazyLoadingEnabled
    • column:關(guān)聯(lián)的外鍵ID
    • property:屬性名
    • javaType:屬性的類型,一般為List.class

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

  • @Options:這個注解對應(yīng)映射語句中的屬性配置。常用屬性如下:

    • useCache=true,
    • flushCache=false,
    • resultSetType=FORWARD_ONLY,
    • statementType=PREPARED,
    • fetchSize= -1
    • timeout=-1 ,
    • useGeneratedKeys=false
    • keyProperty="id"
  • @Param:參數(shù)注解

    當(dāng)需要多個參數(shù)時,此注解用于給每一個參數(shù)定義名稱。否則就會被以它們的順序位置命名,如#{1}、#{2}等。
    使用@Param(“person”),SQL中參數(shù)解析就可以使用#{person}

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

    eg:@SelectKey(statement = "select last_insert_id()" ,keyProperty = "id",keyColumn = "id",resultType = int.class,before = false)
    其中before屬性,默認是true,在執(zhí)行插入語句之前,執(zhí)行select last_insert_id()。如果設(shè)置為flase,則在插入這個語句之后,執(zhí)行select last_insert_id()
    在已經(jīng)被@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;
    //訂單關(guān)聯(lián)的用戶
    private UserEntity user;
    //ignore setter/getter
}
  • UserEntity
public class UserEntity {
    private Integer id;
    private String name;
    //用戶關(guān)聯(lián)的訂單數(shù)據(jù)
    private List<OrderEntity> orders;
    //ignore setter/getter
}    

2、創(chuàng)建OrderDao和UserDao接口

3、在mybatis配置文件上配置對應(yīng)的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、創(chuàng)建OrderTest和UserTest的單元測試類

二、新增訂單數(shù)據(jù)

  • 多參數(shù)新增訂單
/**
  * 多參數(shù)添加訂單數(shù)據(jù)
  * @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);
  • 實體參數(shù)新增訂單
/**
    * 實體參數(shù)添加訂單數(shù)據(jù)
    * @param order 訂單實體
    * @return 返回值大于0表示插入成功
    */
@Insert("INSERT INTO `order`(user_id, amount) VALUES(#{order.userId}, #{order.amount})")
int insertWithEntity(@Param("order") OrderEntity order);
  • 實體參數(shù)新增訂單,并返回新增的訂單ID
/**
    * 實體參數(shù)添加訂單數(shù)據(jù),并返回訂單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);

三、更新訂單數(shù)據(jù)

  • 多參數(shù)更新訂單金額
/**
    * 更新某訂單的金額
    * @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);
  • 實體參數(shù)更新訂單金額
/**
    * 更新某訂單的金額
    * @param order 訂單實體
    * @return 返回值大于0表示更新成功
    */
@Update("UPDATE `order` SET amount=#{order.amount} WHERE id=#{order.id}")
int updateAmountWithEntity(@Param("order") OrderEntity order);

四、刪除訂單數(shù)據(jù)

/**
    * 根據(jù)訂單ID刪除訂單
    * @param id 訂單ID
    * @return 返回值大于0表示刪除成功
    */
@Delete("DELETE FROM `order` WHERE id=#{id}")
int delete(@Param("id") Integer id);

五、查詢?nèi)坑唵螖?shù)據(jù)

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

六、查詢單條訂單數(shù)據(jù)

/**
    * 根據(jù)訂單ID查詢訂單數(shù)據(jù)
    * @param id 訂單ID
    * @return
    */
@Select("SELECT * FROM `order` WHERE id=#{id}")
OrderEntity selectOne(@Param("id") Integer id);

七、查詢訂單以及關(guān)聯(lián)的用戶數(shù)據(jù)

  • 聯(lián)合查詢
/**
    * 獲取訂單數(shù)據(jù)以及關(guān)聯(lián)的用戶信息
    * @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);
  • 嵌套查詢
/**
    * 獲取訂單數(shù)據(jù)以及關(guān)聯(lián)的用戶信息
    * @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);

八、查詢用戶以及關(guān)聯(lián)的訂單數(shù)據(jù)

  • 嵌套查詢,延遲加載
/**
    * 獲取某用戶的數(shù)據(jù)以及關(guān)聯(lián)訂單數(shù)據(jù)。延遲加載
    * @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);
  • 嵌套查詢
/**
    * 獲取某用戶的數(shù)據(jù)以及關(guān)聯(lián)訂單數(shù)據(jù)
    * @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);

九、使用動態(tài)SQL支持復(fù)雜條件的查詢訂單數(shù)據(jù)

  • 用script標簽包裹,像xml文件編寫腳本
public class OrderParam {
    //最小金額
    private BigDecimal minAmount;
    //最大金額
    private BigDecimal maxAmount;
    //用戶ID
    private Integer userId;
    //ignore getter/setter
}   

/**
    * 復(fù)雜的查詢訂單數(shù)據(jù)
    * @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去實現(xiàn)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();
    }
}

 /**
    * 復(fù)雜的查詢訂單數(shù)據(jù)
    * @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();
    }
}

/**
    * 復(fù)雜的查詢訂單數(shù)據(jù)
    * @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);

如果接口有多個參數(shù),在provider中要使用Map<String, Object>來進行接收

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容