# XXXJoin 使用
# Join 使用说明
# 基础 Join 方法
支持三种基础连接方式:
// LEFT JOIN
wrapper.leftJoin(User.class, User::getId, Order::getUserId);
// RIGHT JOIN
wrapper.rightJoin(User.class, User::getId, Order::getUserId);
// INNER JOIN
wrapper.innerJoin(User.class, User::getId, Order::getUserId);
# 使用 JoinLambdaModel
JoinLambdaModel 提供了更灵活的连接配置方式,可以链式配置多个参数:
# 基本参数说明
- clz: 关联表的类
 - joinTableField: 关联表的关联字段
 - masterTableField: 主表的关联字段
 - alias: 关联表别名
 - logicDelete: 是否启用逻辑删除
 - consumer: 关联表的查询条件构造器
 
# 常用示例
- 基础关联
 
// 简单关联
JoinLambdaModel<User, Order> model = JoinLambdaModel.of(
    User.class,
    User::getId,
    Order::getUserId
);
wrapper.leftJoin(model);
// 生成SQL: 
// LEFT JOIN user ON user.id = order.user_id
- 指定别名
 
JoinLambdaModel<User, Order> model = JoinLambdaModel.of(
    User.class,
    User::getId, 
    Order::getUserId,
    "u"
);
wrapper.leftJoin(model);
// 生成SQL:
// LEFT JOIN user u ON u.id = order.user_id
- 指定逻辑删除
 
JoinLambdaModel<User, Order> model = JoinLambdaModel.of(
    User.class,
    User::getId,
    Order::getUserId,
    "u",
    false  // 关闭逻辑删除
);
wrapper.leftJoin(model);
// 生成SQL:
// LEFT JOIN user u ON u.id = order.user_id
- 添加通用关联条件
 
// 定义通用的关联条件
JoinLambdaModel<User, Order> model = JoinLambdaModel.of(
    User.class,
    User::getId,
    Order::getUserId,
    "u",
    false,
    j -> j.eq(User::getStatus, 1)  // 只关联状态正常的用户
);
// 使用并添加特定业务条件
wrapper.leftJoin(model)
       .eq(User::getType, "VIP")   // 添加具体业务相关的查询条件
       .like(User::getName, "张")
       .end();                      // 完成当前表的条件构造,返回主表构造器
// 生成SQL:
// LEFT JOIN user u ON u.id = order.user_id 
// AND u.status = 1                -- 通用条件(在model中定义)
// AND u.type = 'VIP'             -- 业务条件(在链式调用中添加)
// AND u.name LIKE '%张%'
# 最佳实践
- 抽取通用关联条件
 
public class JoinModels {
    public static JoinLambdaModel<User, Order> userOrder() {
        return JoinLambdaModel.of(
            User.class,
            User::getId,
            Order::getUserId,
            "u",
            false,
            j -> j.eq(User::getStatus, 1)    // 通用的状态检查
                 .isNotNull(User::getPhone)   // 通用的非空检查
        );
    }
}
// 使用
wrapper.leftJoin(JoinModels.userOrder())
       .eq(User::getType, "VIP")      // 添加业务相关条件
       .between(User::getCreateTime, startTime, endTime)
       .end();
- 链式调用
 
Joins.of(Order.class)
    .leftJoin(JoinModels.userOrder())
        .eq(User::getType, "VIP")
        .end()
    .leftJoin(JoinModels.productOrder())
        .gt(Product::getPrice, 100)
        .end()
    .select(Order::getId, User::getName, Product::getTitle)
    .list();
- 条件复用示例
 
// 定义通用的关联条件
JoinLambdaModel<User, Order> baseUserJoin = JoinLambdaModel.of(
    User.class,
    User::getId,
    Order::getUserId,
    "u",
    false,
    j -> j.eq(User::getStatus, 1)
);
// 查询VIP用户订单
wrapper.leftJoin(baseUserJoin)
       .eq(User::getType, "VIP")
       .end();
// 查询新注册用户订单
wrapper.leftJoin(baseUserJoin)
       .gt(User::getCreateTime, LocalDateTime.now().minusDays(7))
       .end();
# 注意事项
- 别名使用
 
- 建议始终指定别名,避免多表关联时的列名冲突
 - 别名要具有业务含义,便于理解
 - 同一查询中别名不能重复
 
- 逻辑删除
 
- 默认开启逻辑删除,会自动添加逻辑删除条件
 - 如果确实需要查询已删除数据,可以手动设置 logicDelete 为 false
 - 关闭逻辑删除时要注意数据安全性
 
- 条件构造
 
- consumer 适合定义通用的关联条件
 - 具体业务条件建议在 join 后通过链式调用添加
 - 记得使用 end() 结束当前表的条件构造
 
