# 对象条件构造
# 功能介绍
addObjConditions
是一个用于根据对象属性值自动构建查询条件的功能。它可以将一个对象的非空属性自动转换为对应的查询条件,极大简化了查询条件的编写。
# 注解参数说明
所有条件注解都支持以下三个参数:
tableAlias
- 表别名- 默认为空,表示主表字段
- 用于指定关联表的别名,实现多表查询条件构建
mappingColumn
- 映射列名- 默认为空,使用属性名的下划线形式作为列名
- 当属性名与数据库列名不一致时使用
group
- 条件分组- 默认为空数组,表示该条件始终生效
- 类似于Valid分组功能,可以根据不同场景启用不同的查询条件
# 使用示例
# 基础用法
@Data
public class UserQuery {
@Eq // 等价于 name = ?
private String name;
@Like // 等价于 address LIKE ?
private String address;
@Gt // 等价于 age > ?
private Integer age;
}
// 使用
UserQuery query = new UserQuery();
query.setName("张三");
query.setAddress("北京");
query.setAge(18);
wrapper.addObjConditions(query);
// 生成的SQL:
// SELECT * FROM user
// WHERE name = '张三'
// AND address LIKE '%北京%'
// AND age > 18
# 指定表别名
@Data
public class OrderQuery {
// 主表字段
@Eq
private String orderNo;
// 关联用户表字段
@Eq(tableAlias = "u")
private String userName;
// 关联商品表字段
@Ge(tableAlias = "p")
private BigDecimal price;
@OrderBy
private String orderBy;
}
// 使用
OrderQuery query = new OrderQuery();
query.setOrderNo("OR2024001");
query.setUserName("张三");
query.setOrderBy("orderNo,asc");
query.setPrice(new BigDecimal("100"));
Joins.of(Order.class)
.leftJoin(Users.class,Order::getUserId,Users::getId,'u')
.leftJoin(Product.class,Order::getProductId,Product::getId,'p')
.addObjConditions(query);
// 生成的SQL:
// SELECT * FROM order t
// LEFT JOIN users u ON u.id = t.user_id
// LEFT JOIN product p ON p.id = t.product_id
// WHERE t.order_no = 'OR2024001'
// AND u.user_name = '张三'
// AND p.price >= 100
// Order By order_no asc
# 自定义列名映射
@Data
public class ProductQuery {
// 属性名与列名不一致
@Eq(mappingColumn = "product_name")
private String name;
// 关联表+自定义列名
@Like(tableAlias = "c", mappingColumn = "category_name")
private String categoryName;
}
// 使用
ProductQuery query = new ProductQuery();
query.setName("iPhone");
query.setCategoryName("手机");
Joins.of(Product.class)
.leftJoin(Category.class, Product::getCategoryId, Category::getId,'c')
.addObjConditions(query);
// 生成的SQL:
// SELECT * FROM product t
// LEFT JOIN category c ON c.id = t.category_id
// WHERE t.product_name = 'iPhone'
// AND c.category_name LIKE '%手机%'
# 条件分组
@Data
public class OrderQuery {
@Eq
private String orderNo;
// 列表查询条件 - 创建时间范围
@Ge(mappingColumn = "create_time", group = QueryGroup.List.class)
private LocalDateTime startTime;
@Le(mappingColumn = "create_time", group = QueryGroup.List.class)
private LocalDateTime endTime;
@In(group = QueryGroup.Export.class)
private List<Integer> statusList;
}
// 列表查询
OrderQuery query = new OrderQuery();
query.setOrderNo("OR2024001");
query.setStartTime(LocalDateTime.now().minusDays(7));
query.setEndTime(LocalDateTime.now());
wrapper.addObjConditions(query, QueryGroup.List.class);
// 生成的SQL:
// SELECT * FROM order
// WHERE order_no = 'OR2024001'
// AND create_time >= '2024-01-15 00:00:00'
// AND create_time <= '2024-01-22 00:00:00'
// 导出查询
query.setStatusList(Arrays.asList(1, 2, 3));
wrapper.addObjConditions(query, QueryGroup.Export.class);
// 生成的SQL:
// SELECT * FROM order
// WHERE order_no = 'OR2024001'
// AND status IN (1, 2, 3)
# 支持的条件注解
目前支持以下条件注解:
@Eq
- 等于(=)@Ne
- 不等于(<>)@Gt
- 大于(>)@Ge
- 大于等于(>=)@Lt
- 小于(<)@Le
- 小于等于(<=)@Like
- 模糊查询(LIKE '%值%')@NotLike
- 不包含(NOT LIKE '%值%')@LikeLeft
- 左模糊(LIKE '%值')@LikeRight
- 右模糊(LIKE '值%')@NotLikeLeft
- 不以什么开头(NOT LIKE '%值')@NotLikeRight
- 不以什么结尾(NOT LIKE '值%')@In
- 包含(IN)@NotIn
- 不包含(NOT IN)@Between
- Between
# 支持的排序注解
@OrderBy
- OrderBy排序
# 最佳实践
- 查询对象命名规范
// 推荐使用 实体名 + Query 作为查询对象名称
public class UserQuery { }
public class OrderQuery { }
- 合理使用条件注解
@Data
public class UserQuery {
// 精确匹配的字段使用 @Eq
@Eq
private String status;
// 模糊搜索的字段使用 @Like
@Like
private String keyword;
// 范围查询的开始和结束时间都映射到 create_time 字段
@Ge(mappingColumn = "create_time")
private LocalDateTime startTime;
@Le(mappingColumn = "create_time")
private LocalDateTime endTime;
// 多表关联查询
@Eq(tableAlias = "d")
private String deptName;
}
- 空值处理
// 所有条件注解都会自动过滤空值,无需手动判断
UserQuery query = new UserQuery();
query.setName(null);
query.setAge(18);
wrapper.addObjConditions(query);
// 只会添加 age 的查询条件
- 分组使用
@Data
public class OrderQuery {
// 通用条件
@Eq
private String orderNo;
// 列表查询条件 - 创建时间范围
@Ge(mappingColumn = "create_time", group = QueryGroup.List.class)
private LocalDateTime startTime;
@Le(mappingColumn = "create_time", group = QueryGroup.List.class)
private LocalDateTime endTime;
// 导出条件
@In(group = QueryGroup.Export.class)
private List<Integer> statusList;
}
# 注意事项
- 表别名使用
- 主表字段不需要指定tableAlias
- 关联表字段必须指定tableAlias,且要与join时的别名一致
- tableAlias区分大小写
- 映射列名使用
- 只有属性名与列名不一致时才需要指定
- mappingColumn必须是实际的数据库列名
- 建议统一命名规范,减少映射
- 分组使用
- 建议将分组接口定义在查询对象内部
- 分组接口使用见名知意的命名
- 通用条件不指定group
- 其他注意
- 查询对象中的属性类型要与实体类对应
- 建议将查询对象与实体类分开维护
- 不要在同一字段上使用多个条件注解
通过合理使用这些注解参数,我们可以:
- 实现灵活的多表查询条件构建
- 优雅处理字段映射关系
- 根据不同场景启用不同的查询条件
- 提高代码的可维护性和复用性