Hibernate Criteria API - 添加一个标准:字符串应该在集合中
Posted
技术标签:
【中文标题】Hibernate Criteria API - 添加一个标准:字符串应该在集合中【英文标题】:Hibernate Criteria API - adding a criterion: string should be in collection 【发布时间】:2011-02-13 16:07:50 【问题描述】:我必须关注实体对象
@Entity
public class Foobar
...
private List<String> uuids;
...
现在我想做一个标准查询,它会获取所有 Foobar pojos,其 uuids 列表包含字符串“abc123”,我只是不确定如何制定适当的标准。
【问题讨论】:
【参考方案1】:我假设您使用的是实现 JPA 2.0 的 Hibernate 版本。这是一个 JPA 2.0 解决方案,应该适用于任何兼容的实现。
请使用 JPA 的 @ElementCollection
注释来注释 uuids
。不要使用 Hibernate 的 @CollectionOfElements
,正如其他一些答案 cmets 中提到的那样。后者具有相同的功能,但为being deprecated。
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
s 的方法。
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 3.6.7-Final试过了,还是不行(好像是hibernate的bug)。【参考方案2】:我知道这是一个老问题,但我刚刚遇到这个问题并找到了解决方案。
如果你想使用 Hibernate Criteria,你可以加入你的 uuids
集合并使用它的属性 elements
来匹配元素。就这样:
session.createCriteria(Foobar.class)
.createAlias("uuids", "uuids")
.add(Restrictions.eq("uuids.elements", "MyUUID"))
.list()
【讨论】:
你也可以使用常量CollectionPropertyNames.COLLECTION_ELEMENTS
来代替“元素”。【参考方案3】:
您可以使用下面示例中的查询,也可以将其转换为 NamedQuery。不幸的是,Criteria 似乎没有办法做到这一点。
List<Foobar> result = session
.createQuery("from Foobar f join f.uuids u where u =: mytest")
.setString("mytest", "acb123")
.list();
【讨论】:
【参考方案4】:我发现了一年前的这篇文章,并且我制作了这个方法,如果它可以帮助任何人解决我几个小时前遇到的同样问题。
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();
它适用于“or”语句,但可以很容易地被“and”语句替换。
【讨论】:
【参考方案5】: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)) ;
【讨论】:
【参考方案6】:jira 的 sqlRestriction 解决方案 http://opensource.atlassian.com/projects/hibernate/browse/HHH-869 对我来说似乎是最好的方式,因为我大量使用标准 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));
【讨论】:
【参考方案7】:对于初学者,我认为 Hibernate 不能映射 List<String>
。但是,它可以映射其他实体的列表。
如果你的代码是这样的:
@Entity
public class Foobar
private List<EntityObject> uuids;
...
EntityObject
有一个名为String
的str
属性,标准可能如下所示:
List<Foobar> returns = (List<Foobar>) session
.createCriteria.(Foobar.class, "foobars")
.createAlias("foobars.uuids", "uuids")
.add(Restrictions.like("uuids.str", "%abc123%"))
.list();
【讨论】:
使用字符串列表没有问题,只要用@CollectionOfElements注解即可。您的解决方案需要我创建一个额外的实体类,我希望通过这个非常具体的问题来避免这种情况。以上是关于Hibernate Criteria API - 添加一个标准:字符串应该在集合中的主要内容,如果未能解决你的问题,请参考以下文章
Hibernate Criteria API:获取 n 个随机行
Hibernate Criteria Api 是不是完全防止 SQL 注入
(懒惰)使用 Hibernate Criteria API 的 LEFT OUTER JOIN
Criteria API JPA Hibernate:外键上的不同选择