本文目录导读:

在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);
}
推荐使用方式
生产环境推荐:
- MyBatis + XML:最灵活,适合复杂SQL
- MyBatis-Plus:开发效率高,适合标准CRUD
- Spring Data JPA + Specification:适合标准化的企业应用
简单场景可以使用MyBatis-Plus的条件构造器,复杂查询建议使用MyBatis的XML方式。
需要我详细演示某个方案的完整实现吗?