java Hibernate Criteria API - 添加一个标准:字符串应该在集合中

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2735071/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 22:36:28  来源:igfitidea点击:

Hibernate Criteria API - adding a criterion: string should be in collection

javahibernatejpacriteriacriteria-api

提问by Kim L

I have to following entity object

我必须遵循实体对象


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

Now I'd like to make a criteria query which would fetch all Foobar pojos whose uuids list contains the string "abc123", I'm just not sure how to make the appropriate criterion.

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

回答by Dan LaRocque

I assume you are using a version of Hibernate that implements JPA 2.0. Here's a JPA 2.0 solution that should work with any compliant implementation.

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

Please annotate uuidswith JPA's @ElementCollectionannotation. Don't use Hibernate's @CollectionOfElementsas mentioned in some of the other answer comments. The latter has equivalent functionality but is being deprecated.

uuids使用 JPA 的@ElementCollection注释进行注释。不要@CollectionOfElements像其他一些答案评论中提到的那样使用 Hibernate 。后者具有等效功能,但已被弃用

Foobar.javawill look approximately like this:

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, ...

}

Here's how you can build a CriteriaQueryto select all Foobars whose uuidscontain "abc123".

以下是如何构建 aCriteriaQuery以选择包含“abc123”的所有Foobars uuids

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
    }
}

I made a self-contained proof-of-concept program while playing with this. I can't push it out right now. Please comment if you want the POC pushed to github.

我在玩这个时制作了一个独立的概念验证程序。我现在不能把它推出来。如果您想将 POC 推送到 github,请发表评论。

回答by Maciej Dobrowolski

I know this is old question, but I have just encountered this issue and found solution.

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

If you want to use Hibernate Criteria you can join your uuidscollection and use its property elementsto match elements. Just like that:

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

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

回答by Christian

I've found this post from one year ago, and I've made this method, if it can help anybody with the same problem I had a few hours ago.

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

    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();

Made the same with a group of strings too.

用一组弦也做同样的事情。

    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();
    }

It works with "or" statements, but can easily be replaced by "and" statements.

它适用于“或”语句,但可以很容易地被“和”语句替换。

回答by Rachel

You could use a Query as in the example below or you could convert this to a NamedQuery. Unfortunately there doesn't seem to be a way to do this with Criteria.

您可以使用下面示例中的查询,也可以将其转换为 NamedQuery。不幸的是,似乎没有办法用 Criteria 做到这一点。

List<Foobar> result = session
     .createQuery("from Foobar f join f.uuids u where u =: mytest")
     .setString("mytest", "acb123")
     .list();

回答by Thierry

What you are asking is not supported out of the box by hibernate. See http://opensource.atlassian.com/projects/hibernate/browse/HHH-869

休眠不支持开箱即用的功能。见http://opensource.atlassian.com/projects/hibernate/browse/HHH-869

Here is a workaround available in the jira ticket :

这是 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)) ;

回答by Pavel Kotlov

The solution with the sqlRestriction from jira http://opensource.atlassian.com/projects/hibernate/browse/HHH-869seemed the best way to go for me since i heavily use criteria api. I had to edit Thierry's code so it worked in my case

来自 jira http://opensource.atlassian.com/projects/hibernate/browse/HHH-869的 sqlRestriction 的解决方案 对我来说似乎是最好的方法,因为我大量使用标准 api。我不得不编辑蒂埃里的代码,所以它适用于我的情况

Model:

模型:

@Entity
public class PlatformData
{
  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private long iID;

  private List<String> iPlatformAbilities = new ArrayList<String>();
}

Criteria call:

标准调用:

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));

回答by Lars Andren

For starters, I don't think Hibernate can map a List<String>. However, it can map a list of other entities.

首先,我不认为 Hibernate 可以映射List<String>. 但是,它可以映射其他实体的列表。

So if your code was something like this:

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

@Entity
public class Foobar {

    private List<EntityObject> uuids;
    ...
}

And the EntityObjecthas a String-property called str, the criteria could look like this:

并且EntityObject有一个String名为的-property str,条件可能如下所示:

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