Java案例怎么实现动态SQL?

wen java案例 29

本文目录导读:

Java案例怎么实现动态SQL?

  1. MyBatis 动态SQL(最常用)
  2. MyBatis-Plus (更简便)
  3. Spring Data JPA 规格查询
  4. 使用QueryDSL(类型安全)
  5. 手动拼接SQL(不推荐,但可用于简单场景)
  6. 推荐使用方式

在Java中实现动态SQL主要有以下几种主流方案,我按推荐程度排序给你介绍:

MyBatis 动态SQL(最常用)

MyBatis提供了XML和注解两种方式的动态SQL。

XML方式示例:

<select id="findUsers" parameterType="map" resultType="User">
    SELECT * FROM users
    <where>
        <if test="username != null and username != ''">
            AND username LIKE CONCAT('%', #{username}, '%')
        </if>
        <if test="age != null">
            AND age = #{age}
        </if>
        <if test="email != null">
            AND email = #{email}
        </if>
    </where>
    <if test="orderBy != null">
        ORDER BY ${orderBy}
    </if>
</select>

注解方式示例:

@Select("<script>" +
        "SELECT * FROM users" +
        "<where>" +
        "<if test='username != null'>AND username = #{username}</if>" +
        "<if test='age != null'>AND age = #{age}</if>" +
        "</where>" +
        "</script>")
List<User> findUsers(@Param("username") String username, 
                     @Param("age") Integer age);

MyBatis-Plus (更简便)

基于MyBatis的增强工具,提供了更简洁的动态SQL:

// 使用条件构造器
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.like(StringUtils.isNotBlank(username), "username", username)
       .eq(age != null, "age", age)
       .orderByDesc("create_time");
List<User> users = userMapper.selectList(wrapper);

Spring Data JPA 规格查询

使用JPA的Specification实现动态查询:

public class UserSpecification {
    public static Specification<User> dynamicQuery(UserQueryDTO dto) {
        return (root, query, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            if (StringUtils.isNotBlank(dto.getUsername())) {
                predicates.add(criteriaBuilder.like(
                    root.get("username"), "%" + dto.getUsername() + "%"
                ));
            }
            if (dto.getAge() != null) {
                predicates.add(criteriaBuilder.equal(
                    root.get("age"), dto.getAge()
                ));
            }
            return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
        };
    }
}
// 使用
List<User> users = userRepository.findAll(
    UserSpecification.dynamicQuery(queryDTO)
);

使用QueryDSL(类型安全)

提供编译时类型检查,避免SQL拼写错误:

// 需要生成Q类
QUser user = QUser.user;
JPAQuery<User> query = new JPAQuery<>(entityManager);
JPAQuery<User> dynamicQuery = query.from(user)
    .where(user.username.containsIgnoreCase(searchDTO.getUsername())
           .and(user.age.eq(searchDTO.getAge())));
List<User> users = dynamicQuery.fetch();

手动拼接SQL(不推荐,但可用于简单场景)

public String buildDynamicSql(UserQueryDTO params) {
    StringBuilder sql = new StringBuilder("SELECT * FROM users WHERE 1=1");
    List<Object> params = new ArrayList<>();
    if (params.getUsername() != null && !params.getUsername().isEmpty()) {
        sql.append(" AND username LIKE ?");
        params.add("%" + params.getUsername() + "%");
    }
    if (params.getAge() != null) {
        sql.append(" AND age = ?");
        params.add(params.getAge());
    }
    // 使用Spring的JdbcTemplate执行
    return jdbcTemplate.query(sql.toString(), params.toArray(), rowMapper);
}

推荐使用方式

生产环境推荐

  1. MyBatis + XML:最灵活,适合复杂SQL
  2. MyBatis-Plus:开发效率高,适合标准CRUD
  3. Spring Data JPA + Specification:适合标准化的企业应用

简单场景可以使用MyBatis-Plus的条件构造器,复杂查询建议使用MyBatis的XML方式。

需要我详细演示某个方案的完整实现吗?

抱歉,评论功能暂时关闭!