[英]Hibernate Criteria API - adding a criterion: string should be in collection
我必须遵循实体对象
@Entity
public class Foobar {
...
private List<String> uuids;
...
}
现在我想制作一个条件查询来获取所有Foobar pojos,其uuids列表包含字符串“abc123”,我只是不确定如何制定适当的标准。
我假设您使用的是实现JPA 2.0的Hibernate版本。 这是一个JPA 2.0解决方案,可以与任何兼容的实现一起使用。
请使用JPA的@ElementCollection
注释来注释uuids
。 不要像其他一些答案评论中提到的那样使用Hibernate的@CollectionOfElements
。 后者具有相同的功能,但已被弃用 。
Foobar.java
看起来大致如下:
@Entity
public class Foobar implements Serializable {
// You might have some other id
@Id
private Long id;
@ElementCollection
private List<String> uuids;
// Getters/Setters, serialVersionUID, ...
}
以下是如何构建CriteriaQuery
以选择其uuids
包含“abc123”的所有Foobar
。
public void getFoobars() {
{
EntityManager em = ... // EM by injection, EntityManagerFactory, whatever
CriteriaBuilder b = em.getCriteriaBuilder();
CriteriaQuery<Foobar> cq = b.createQuery(Foobar.class);
Root<Foobar> foobar = cq.from(Foobar.class);
TypedQuery<Foobar> q = em.createQuery(
cq.select(foobar)
.where(b.isMember("abc123", foobar.<List<String>>get("uuids"))));
for (Foobar f : q.getResultList()) {
// Do stuff with f, which will have "abc123" in uuids
}
}
在玩这个游戏的过程中,我制作了一个独立的概念验证程序。 我现在不能把它推出去。 如果您希望将POC推送到github,请发表评论。
我知道这是一个老问题,但我刚遇到这个问题并找到了解决方案。
如果您想使用Hibernate Criteria,您可以加入您的uuids
集合并使用其属性elements
来匹配元素。 就像那样:
session.createCriteria(Foobar.class)
.createAlias("uuids", "uuids")
.add(Restrictions.eq("uuids.elements", "MyUUID"))
.list()
我在一年前找到了这篇文章,并且我已经制作了这个方法,如果它可以帮助任何人在几小时前遇到同样的问题。
Public List<EntityObject> getHasString(String string) {
return getSession().createCriteria(EntityObject.class)
.add(Restriction.like("property-name", string, MatchMode.ANYWHERE).ignoreCase();
.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
.list();
也用一组字符串做同样的事情。
public List<EntityObject> getByStringList(String[] tab) {
Criterion c = Restrictions.like("property-name", tab[tab.length-1], MatchMode.ANYWHERE).ignoreCase();
if(tab.length > 1) {
for(int i=tab.length-2; i >= 0 ; i--) {
c = Restrictions.or(Restrictions.like("property-name",tab[i], MatchMode.ANYWHERE).ignoreCase(), c);
}
}
return getSession().createCriteria(EntityObject.class)
.add(c)
.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
.list();
}
它适用于“或”语句,但很容易被“和”语句替换。
您可以使用下面示例中的Query,也可以将其转换为NamedQuery。 不幸的是,似乎没有办法用Criteria做到这一点。
List<Foobar> result = session
.createQuery("from Foobar f join f.uuids u where u =: mytest")
.setString("mytest", "acb123")
.list();
hibernate不支持开箱即用的问题。 请参见http://opensource.atlassian.com/projects/hibernate/browse/HHH-869
以下是jira票证中提供的解决方法:
entityCriteria.add(Restrictions.sqlRestriction(
"fooAlias.id in (select e.id from foobar_table e, values_table v" +
" where e.id = v.entity_id and v.field = ?)", "abc123"), Hibernate.String)) ;
来自jira http://opensource.atlassian.com/projects/hibernate/browse/HHH-869的sqlRestriction解决方案似乎是最好的方式,因为我大量使用标准api。 我不得不编辑Thierry的代码,因此它适用于我的情况
模型:
@Entity
public class PlatformData
{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long iID;
private List<String> iPlatformAbilities = new ArrayList<String>();
}
标准电话:
tCriteria.add(Restrictions.sqlRestriction(
"{alias}.id in (select e.id from platformData e, platformdata_platformabilities v"
+ " where e.id = v.platformdata_id and v.element = ? )", aPlatformAbility.toString(),
Hibernate.STRING));
对于初学者,我认为Hibernate不能映射List<String>
。 但是,它可以映射其他实体的列表。
所以如果你的代码是这样的:
@Entity
public class Foobar {
private List<EntityObject> uuids;
...
}
并且EntityObject
有一个名为str
的String
-property,标准可能如下所示:
List<Foobar> returns = (List<Foobar>) session
.createCriteria.(Foobar.class, "foobars")
.createAlias("foobars.uuids", "uuids")
.add(Restrictions.like("uuids.str", "%abc123%"))
.list();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.