我在将 JPA 与 Querydsl 和 Hibernate 一起用于数据存储管理时遇到了问题。示例模型如下:
@Entity
public class User {
....
@ManyToOne
@JoinColumn(name = "CATEGORY_ID")
private Category category;
}
@Entity
public class Category {
..
private String acronym;
@OneToMany(mappedBy = "category")
List<User> userList;
}
在我的 Spring MVC webapp 中,我有一个带有用户参数和 orderBy 选择的搜索表单。 orderBy 选择可以是 User 属性或 Category 属性。 orderBy 参数存储为 Map (f.e. {"login": "adm", {"firstName": "John"}。搜索函数接收搜索参数(作为字符串)和上面带有订单规范的 map 。简化代码订购方式如下:
Map<String, String> orderByMap = new HashMap<String, String>();
orderByMap.put("firstName", "asc");
orderByMap.put("unit.acronym", "desc");
PathBuilder<User> pbu = new PathBuilder<User>(User.class, "user");
....
for (Map.Entry<String, String> order : orderByMap.entrySet())
{
// for simplicity I've omitted asc/desc chooser
query.orderBy(pbu.getString(order.getKey()).asc());
}
当我想引入按类别参数排序时,问题就开始了,比如 {"category.acronym", "desc"}。正如解释的那样 here ,上面的代码将使 querydsl 使用与类别表的交叉连接并省略没有类别的用户,这不是预期的行为。
我知道,我必须引入带类别的左连接并使用别名进行排序以使其正常工作,但我正在寻找动态执行此操作的有效方法。剥离每个字符串以查找类别或任何其他实体(如“user.category.subcategory.propetry”)会引入很多丑陋的代码,我宁愿不这样做。
如果能提供一些更优雅的解决方案,我将不胜感激。
最佳答案
我没有将实现的原型(prototype)添加到 Querydsl 的测试端 https://github.com/mysema/querydsl/issues/582
如果这是一个常见的用例,我会考虑直接集成到 Querydsl 中
public class OrderHelper {
private static final Pattern DOT = Pattern.compile("\\.");
public static PathBuilder<?> join(JPACommonQuery<?> query, PathBuilder<?> builder, Map<String, PathBuilder<?>> joins, String path) {
PathBuilder<?> rv = joins.get(path);
if (rv == null) {
if (path.contains(".")) {
String[] tokens = DOT.split(path);
String[] parent = new String[tokens.length - 1];
System.arraycopy(tokens, 0, parent, 0, tokens.length - 1);
String parentKey = StringUtils.join(parent, ".");
builder = join(query, builder, joins, parentKey);
rv = new PathBuilder(Object.class, StringUtils.join(tokens, "_"));
query.leftJoin((EntityPath)builder.get(tokens[tokens.length - 1]), rv);
} else {
rv = new PathBuilder(Object.class, path);
query.leftJoin((EntityPath)builder.get(path), rv);
}
joins.put(path, rv);
}
return rv;
}
public static void orderBy(JPACommonQuery<?> query, EntityPath<?> entity, List<String> order) {
PathBuilder<?> builder = new PathBuilder(entity.getType(), entity.getMetadata());
Map<String, PathBuilder<?>> joins = Maps.newHashMap();
for (String entry : order) {
String[] tokens = DOT.split(entry);
if (tokens.length > 1) {
String[] parent = new String[tokens.length - 1];
System.arraycopy(tokens, 0, parent, 0, tokens.length - 1);
PathBuilder<?> parentAlias = join(query, builder, joins, StringUtils.join(parent, "."));
query.orderBy(parentAlias.getString(tokens[tokens.length - 1]).asc());
} else {
query.orderBy(builder.getString(tokens[0]).asc());
}
}
}
}
关于java - Generic querydsl orderBy 带左连接的动态路径生成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20287194/