文章内容输出来源:拉勾教育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 >= #{minAmount}</if>",
"<if test='null != maxAmount'>and amount <= #{maxAmount}</if>",
"</where>",
"</script>"
})
List<OrderEntity> selectListByCondition2(OrderParam param);
- 用Provider去实现SQL拼接
- 示例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);
- 示例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>来进行接收
网友评论