如何选择父母对象并按孩子的属性排序
问题描述:
免责声明:我们的数据库是遗留的,并不完全理想。我试图解决JPA映射问题来处理超出我的工作范围的非理想DB。请不要DB设计评论...如何选择父母对象并按孩子的属性排序
我必须做2件事。我必须获取一个父项及其子项,只要匹配其中一个子项的属性,并且必须通过该子项的属性来排序返回的对象。
我想知道如果我可以使用“获取联接”来做到这一点,而不是常规联接。
的类/映射基本上是这样的:
@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,而不是按名称进行过滤。
这种行为,特别是上面的示例SQL查询如何在JPA中实现?
如果我可以或应该使用'fetch join'来做这件事,我会怎么做呢?
答
正如您添加了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;
}
最后,你需要让你的会话过滤器:
Session session = ...;
session.enableFilter("myFilter").setParameter("nameParameter", "Geordi La Forge");
Profile profile = ...;
List<Account> geordiAccounts=profile.getAccounts();
这是我如何做到这一点的猜测。也许它会激励有人改进它。有关于过滤器的文档http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html_single/#objectstate-filters
谢谢。这应该工作。是的,我实际上并没有看到我们改变了我们的JPA实施。 – lostdorje 2014-10-03 05:47:07