在java后端开发中,动态sql语句的构建是非常常见的需求,特别是在处理复杂查询条件时。以下是几种常用的实现方式:
1. 使用jdbc动态拼接sql
这是最基础的方式,但容易导致sql注入风险,不推荐在生产环境使用。
public list<user> findusers(string name, integer age, string email) {
connection conn = null;
preparedstatement stmt = null;
resultset rs = null;
list<user> users = new arraylist<>();
try {
conn = datasource.getconnection();
// 基础sql
stringbuilder sql = new stringbuilder("select * from users where 1=1");
// 动态添加条件
list<object> params = new arraylist<>();
if (name != null) {
sql.append(" and name = ?");
params.add(name);
}
if (age != null) {
sql.append(" and age = ?");
params.add(age);
}
if (email != null) {
sql.append(" and email like ?");
params.add("%" + email + "%");
}
stmt = conn.preparestatement(sql.tostring());
// 设置参数
for (int i = 0; i < params.size(); i++) {
stmt.setobject(i + 1, params.get(i));
}
rs = stmt.executequery();
while (rs.next()) {
user user = new user();
user.setid(rs.getint("id"));
user.setname(rs.getstring("name"));
user.setage(rs.getint("age"));
user.setemail(rs.getstring("email"));
users.add(user);
}
} catch (sqlexception e) {
e.printstacktrace();
} finally {
// 关闭资源
}
return users;
}2. 使用jpa criteria api
jpa提供了类型安全的动态查询构建方式:
public list<user> findusers(string name, integer age, string email) {
criteriabuilder cb = entitymanager.getcriteriabuilder();
criteriaquery<user> query = cb.createquery(user.class);
root<user> root = query.from(user.class);
list<predicate> predicates = new arraylist<>();
if (name != null) {
predicates.add(cb.equal(root.get("name"), name));
}
if (age != null) {
predicates.add(cb.equal(root.get("age"), age));
}
if (email != null) {
predicates.add(cb.like(root.get("email"), "%" + email + "%"));
}
query.where(predicates.toarray(new predicate[0]));
return entitymanager.createquery(query).getresultlist();
}3. 使用spring data jpa的specification
spring data jpa提供了更简洁的specification方式:
public list<user> findusers(string name, integer age, string email) {
return userrepository.findall((root, query, cb) -> {
list<predicate> predicates = new arraylist<>();
if (name != null) {
predicates.add(cb.equal(root.get("name"), name));
}
if (age != null) {
predicates.add(cb.equal(root.get("age"), age));
}
if (email != null) {
predicates.add(cb.like(root.get("email"), "%" + email + "%"));
}
return cb.and(predicates.toarray(new predicate[0]));
});
}4. 使用mybatis动态sql
mybatis提供了强大的动态sql功能:
mapper接口
public interface usermapper {
list<user> findusers(@param("name") string name,
@param("age") integer age,
@param("email") string email);
}xml映射文件
<select id="findusers" resulttype="user">
select * from users
<where>
<if test="name != null">
and name = #{name}
</if>
<if test="age != null">
and age = #{age}
</if>
<if test="email != null">
and email like concat('%', #{email}, '%')
</if>
</where>
</select>动态sql标签说明
<if>: 条件判断<where>: 自动处理where关键字和and/or前缀<choose>,<when>,<otherwise>: 类似switch-case<foreach>: 遍历集合<set>: 更新时自动处理set关键字和逗号
5. 使用mybatis-plus的条件构造器
mybatis-plus提供了更便捷的查询条件构造方式:
public list<user> findusers(string name, integer age, string email) {
querywrapper<user> querywrapper = new querywrapper<>();
if (name != null) {
querywrapper.eq("name", name);
}
if (age != null) {
querywrapper.eq("age", age);
}
if (email != null) {
querywrapper.like("email", email);
}
return usermapper.selectlist(querywrapper);
}6. 使用jooq动态sql
jooq提供了类型安全的dsl:
public list<user> findusers(string name, integer age, string email) {
return dslcontext.selectfrom(users)
.where(name == null ? nocondition() : users.name.eq(name))
.and(age == null ? nocondition() : users.age.eq(age))
.and(email == null ? nocondition() : users.email.like("%" + email + "%"))
.fetchinto(user.class);
}最佳实践建议
- 安全性: 始终使用参数化查询,防止sql注入
- 可读性: 保持sql语句清晰易读
- 性能: 考虑索引使用情况,避免全表扫描
- 维护性: 复杂查询考虑使用注解或xml分离
- 工具选择:
- 简单项目: spring data jpa specification
- 中等复杂度: mybatis动态sql
- 高度灵活需求: jooq
到此这篇关于java mysql动态语句编写实现方式的文章就介绍到这了,更多相关java mysql动态语句内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论