Hibernate Criteria API – 添加标准:字符串应该在集合中

我必须遵循实体对象

@Entity public class Foobar { ... private List uuids; ... } 

现在我想制作一个标准查询来获取所有Foobar pojos,其uuids列表包含字符串“abc123”,我只是不确定如何制定适当的标准。

我假设您使用的是实现JPA 2.0的Hibernate版本。 这是一个JPA 2.0解决方案,应该适用于任何兼容的实现。

请使用JPA的@ElementCollection注释来注释uuids 。 不要像其他一些答案评论中提到的那样使用Hibernate的@CollectionOfElements 。 后者具有相同的function,但已被弃用 。

Foobar.java看起来大致如下:

 @Entity public class Foobar implements Serializable { // You might have some other id @Id private Long id; @ElementCollection private List uuids; // Getters/Setters, serialVersionUID, ... } 

以下是如何构建CriteriaQuery以选择其uuids包含“abc123”的所有Foobar

 public void getFoobars() { { EntityManager em = ... // EM by injection, EntityManagerFactory, whatever CriteriaBuilder b = em.getCriteriaBuilder(); CriteriaQuery cq = b.createQuery(Foobar.class); Root foobar = cq.from(Foobar.class); TypedQuery q = em.createQuery( cq.select(foobar) .where(b.isMember("abc123", foobar.>get("uuids")))); for (Foobar f : q.getResultList()) { // Do stuff with f, which will have "abc123" in uuids } } 

在玩这个游戏的过程中,我制作了一个独立的概念validation程序。 我现在不能把它推出去。 如果你想把POC推到github,请评论。

我知道这是一个老问题,但我刚遇到这个问题并找到了解决方案。

如果您想使用Hibernate Criteria,您可以加入您的uuids集合并使用其属性elements来匹配元素。 就像那样:

 session.createCriteria(Foobar.class) .createAlias("uuids", "uuids") .add(Restrictions.eq("uuids.elements", "MyUUID")) .list() 

我在一年前找到了这篇文章,并且我已经制作了这个方法,如果它可以帮助任何人在几个小时前遇到同样的问题。

  Public List 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 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 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 iPlatformAbilities = new ArrayList(); } 

标准电话:

 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 。 但是,它可以映射其他实体的列表。

所以如果你的代码是这样的:

 @Entity public class Foobar { private List uuids; ... } 

并且EntityObject有一个名为strString -property,标准可能如下所示:

 List returns = (List) session .createCriteria.(Foobar.class, "foobars") .createAlias("foobars.uuids", "uuids") .add(Restrictions.like("uuids.str", "%abc123%")) .list();