免责声明:我们的数据库是遗产,并不完全理想。我正在尝试解决JPA映射问题以处理非理想的数据库,这超出了我的工作范围。请不要DB设计评论...
我必须做两件事。我必须获取一个父项及其子项,给定一个子项的属性匹配,我必须按子项的属性对返回的对象进行排序。
我想知道我是否可以使用“获取加入”来代替常规连接。
类/映射基本上如下所示:
@Entity
@Table(name = "profiles")
public class Profile {
@Id
private Long id;
@OneToMany(mappedBy = "profile", fetch = FetchType.LAZY)
// @Where(clause = "deleted is null or deleted = 'N'") (1)
private List<Account> accounts;
<...snip...>
}
@Entity
@Table(name = "accounts")
public class Account {
@Id
private Long id;
@ManyToOne
@JoinColumn(name = "profile_id", nullable = false, insertable = true, updatable = false)
private Profile profile;
private String name;
<...snip...>
}
基本上我想要的SQL是这样的:
select p.*, a.*
from profiles p, accounts a
where a.profile_id = p.id and lower(a.name) like '%some_search_text%'
order by lower(a.name);
问题是构建一个JPA查询,如:
String searchText = "%foobar%";
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Profile> criteriaQuery = criteriaBuilder.createQuery(Profile.class);
Root<Profile> profile = criteriaQuery.from(Profile.class);
Join<Profile, Account> profileAccountJoin = profile.join(Profile_.accounts);
criteriaQuery.where(
criteriaBuilder.like(
criteriaBuilder.lower(profileAccountJoin.get(column).as(String.class)), searchText);
criteriaQuery.orderBy(profileAccountJoin.get(Account_.name)); // ??? this maybe works
TypedQuery<Profile> query = entityManager.createQuery(criteriaQuery);
List<Profile> results = query.getResultList();
我会得到一个孩子匹配的个人资料列表。但是后来当转换为DTO并执行profile.getAccounts()时,我将获得profile_id上匹配的所有帐户,而不是按名称过滤。
如何在JPA中实现此行为,特别是上面的示例SQL查询?
如果我能够或应该使用“获取加入”来完成此操作,我将如何解决这个问题?
答案 0 :(得分:0)
当您添加hibernate
标记时,我想知道您是否乐意使用特定于Hibernate的注释Filter
。您可以在Account
上定义一个过滤器,用于过滤与个人资料相关联的帐户。这可能是你如何做到的:
在帐户中:
Profile
然后在个人资料中:
import org.hibernate.annotations.FilterDef;
import org.hibernate.annotations.ParamDef;
@Entity
@FilterDef(name = "myFilter", parameters = @ParamDef(name = "nameParameter", type = "string"))
@Table(name = "accounts")
public class Account {
...
最后,您需要为会话启用过滤器:
@OneToMany(mappedBy = "profile", fetch = FetchType.LAZY)
@Filter(name = "myFilter", condition = ":nameParameter = name")
private List<Account> accounts;
public List<Account> getAccounts() {
return accounts;
}
这是我对如何做到这一点的猜测。也许它会鼓励有人改进它。有关http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html_single/#objectstate-filters
过滤器的文档