Hibernate Criteria API - добавление критерия: строка должна быть в коллекции - PullRequest
6 голосов
/ 29 апреля 2010

Я должен к следующему объекту


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

Теперь я хотел бы сделать запрос критерия, который бы выбрал все poj Foobar, чей список uuids содержит строку "abc123", я просто не уверен, как сделать соответствующий критерий.

Ответы [ 7 ]

7 голосов
/ 30 апреля 2010

Я предполагаю, что вы используете версию Hibernate, которая реализует JPA 2.0. Вот решение JPA 2.0, которое должно работать с любой совместимой реализацией.

Пожалуйста, аннотируйте uuids аннотацией @ElementCollection JPA. Не используйте @CollectionOfElements Hibernate, как упомянуто в некоторых других комментариях. Последний имеет эквивалентную функциональность, но устарел .

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, чтобы выбрать все Foobar s, в которых uuids содержится "abc123".

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.

3 голосов
/ 01 июля 2016

Я знаю, что это старый вопрос, но я только что столкнулся с этой проблемой и нашел решение.

Если вы хотите использовать Hibernate Criteria, вы можете присоединиться к своей коллекции uuids и использовать ее свойство elements для сопоставления элементов. Просто так:

session.createCriteria(Foobar.class)
    .createAlias("uuids", "uuids")
    .add(Restrictions.eq("uuids.elements", "MyUUID"))
    .list() 
2 голосов
/ 22 июня 2011

Я нашел этот пост год назад, и я сделал этот метод, если он может помочь кому-либо с той же проблемой, что у меня была несколько часов назад.

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

Он работает с операторами "или", но может быть легко заменен операторами "и".

1 голос
/ 29 апреля 2010

То, что вы спрашиваете, не поддерживается в спящем режиме. Смотри 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)) ;
1 голос
/ 29 апреля 2010

Вы можете использовать запрос, как в примере ниже, или вы можете преобразовать его в NamedQuery. К сожалению, кажется, нет способа сделать это с критериями.

List<Foobar> result = session
     .createQuery("from Foobar f join f.uuids u where u =: mytest")
     .setString("mytest", "acb123")
     .list();
0 голосов
/ 13 ноября 2012

Решение с sqlRestriction от Jira http://opensource.atlassian.com/projects/hibernate/browse/HHH-869 Казалось, лучший способ пойти для меня, так как я интенсивно использую критерии API. Мне пришлось редактировать код Тьерри, чтобы он работал в моем случае

Модель:

@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));
0 голосов
/ 29 апреля 2010

Для начала, я не думаю, что 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();
...