2010-04-29 15 views

Respuesta

7

Asumo que está utilizando una versión de Hibernate que implementa la APP 2.0. Aquí hay una solución JPA 2.0 que debería funcionar con cualquier implementación compatible.

Anote uuids con la anotación de JPA @ElementCollection. No utilice el @CollectionOfElements de Hibernate como se menciona en algunos de los otros comentarios de respuesta. Este último tiene una funcionalidad equivalente, pero es being deprecated.

Foobar.java se verá aproximadamente así:

@Entity 
public class Foobar implements Serializable { 

    // You might have some other id 
    @Id 
    private Long id; 

    @ElementCollection 
    private List<String> uuids; 

    // Getters/Setters, serialVersionUID, ... 

} 

Así es como se puede construir un CriteriaQuery para seleccionar todos los Foobar s cuyos uuids contener "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 
    } 
} 

Hice un programa autónomo de prueba de concepto mientras jugaba con esto. No puedo sacarlo ahora mismo. Comente si desea que el POC se envíe a github.

+0

Probado con hibernación 3.6.7-Final y no funciona (parece ser un error en hibernación). – greuze

-2

Para empezar, no creo que Hibernate pueda asignar un List<String>. Sin embargo, puede mapear una lista de otras entidades.

Así que si su código fue algo como esto:

@Entity 
public class Foobar { 

    private List<EntityObject> uuids; 
    ... 
} 

Y el EntityObject tiene un String -property llamados str, el criterio podría tener este aspecto:

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

No hay problema en usar una lista de cadenas, simplemente anótelo con @CollectionOfElements. Su solución requiere que haga una clase de entidad adicional, algo que esperaba evitar con esta pregunta muy específica. –

1

Se podría utilizar una consulta como en el ejemplo a continuación o puede convertir esto a una NamedQuery. Desafortunadamente, no parece haber una manera de hacer esto con Criteria.

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

Lo que estás pidiendo no es compatible de forma inmediata con hibernate. Ver http://opensource.atlassian.com/projects/hibernate/browse/HHH-869

Aquí hay una solución disponible en el billete 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)) ; 
2

He encontrado esta publicación de hace un año, y he hecho este método, si puede ayudar a alguien con el mismo problema que tuve hace unas horas.

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

Hecho lo mismo con un grupo de cuerdas también.

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

Funciona con declaraciones "o", pero puede ser fácilmente reemplazado por declaraciones "y".

0

La solución con el sqlRestriction de jira http://opensource.atlassian.com/projects/hibernate/browse/HHH-869 me pareció la mejor opción ya que utilizo mucho los criterios api. Tuve que editar el código de Thierry por lo que funcionó en mi caso

Modelo:

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

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

Criterios llaman:

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

Sé que esto es cuestión de edad, pero sólo he encontrado con este tema y solución encontrada

Si desea utilizar los criterios de Hibernate, puede unirse a su colección uuids y utilizar su propiedad elements para hacer coincidir los elementos. Solo así:

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

También puede usar en lugar de "elementos" la constante 'CollectionPropertyNames.COLLECTION_ELEMENTS'. –

Cuestiones relacionadas