Cómo consultar entidades por su valor de colección

Estoy usando jpa y tengo la siguiente entidad:

@Entity
@Table(name="favorites_folders")
public class FavoritesFolder {

     private static final long serialVersionUID = 1L;

     @Id
     private String id;

     @NotNull
     @Size(min = 1, max = 50)
     public String name;

     @ElementCollection(fetch = FetchType.LAZY)
     @CollectionTable(
        name="favorites_products",
        joinColumns=@JoinColumn(name="folder_id")
        )
     @Column(name="product_id")
     @NotNull
     private Set<String> productsIds = new HashSet<String>();
}

Lo que quiero hacer es conseguir un conjunto de FavoritesFolder entidades que contienen la cadena "favorite-id" en su productsIds conjunto de miembros

Alguien sabe como se puede hacer en API de criterios?

Actualizar:
Estoy pensando que el siguiente sql debería funcionar, pero no estoy seguro de cómo hacerlo en ninguno de los dos. JPQL or Criteria API:

select * from favorites_folders join favorites_products on favorites_folders.id = favorites_products.folder_id where favorites_products.product_id = 'favorite-id'

preguntado el 22 de mayo de 12 a las 20:05

3 Respuestas

Para obtener un conjunto de entidades FavoritesFolder que contengan la cadena "favorite-id" en su conjunto de miembros de Ids de productos utilizando la API de criterios, debe hacer lo siguiente:

CriteriaBuilder cb = em.getCriteriaBuilder(); //em is EntityManager
CriteriaQuery<FavoritesFolder> cq = cb.createQuery(FavoritesFolder.class);
Root<FavoritesFolder> root = cq.from(FavoritesFolder.class);

Expression<Collection<String>> productIds = root.get("productsIds");
Predicate containsFavoritedProduct = cb.isMember("favorite-id", productIds);

cq.where(containsFavoritedProduct);

List<FavoritesFolder> favoritesFolders = em.createQuery(cq).getResultList();

Más información sobre Colecciones en JPQL y consultas de criterios.

contestado el 23 de mayo de 12 a las 10:05

Sé que en este tema nos estamos refiriendo a ID y, por lo tanto, tienen que ser IGUALES para que coincidan, pero digamos que tenemos un Collection<String> en cambio, ¿podemos hacer esencialmente lo mismo pero en lugar de necesitar que un artículo sea equal, podríamos tener un elemento COINCIDIR usando LIKE ? - dominicbri7

@dominicbri7 en un tema relacionado pregunta Encontré la solución. Use el método de unión en la clase raíz cb.like(from.join("apples").get("color"), textParameter) - cirovladimir

Solo otra forma de usar IN

@Entity
public class UserCategory implements Serializable {
private static final long    serialVersionUID    = 8261676013650495854L;

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

@ElementCollection
private List<String> categoryName;


(...)
}

Luego puede escribir una consulta de Criterios como

    CriteriaBuilder cb = entityManager.getCriteriaBuilder();
    CriteriaQuery<UserCategory> q = cb.createQuery(UserCategory.class);
    Root<UserCategory> root = q.from(UserCategory.class);

    Predicate predicate = cb.conjunction();
    Predicate p1 = cb.equal(root.get(UserCategory_.targetSiteType), siteType.getName());
    Predicate p2 = root.get(UserCategory_.categoryName).in(category);
    predicate = cb.and(p1,p2);

    q.where(predicate);

    TypedQuery<UserCategory> tq = entityManager.createQuery(q);
    List<UserCategory> all = tq.getResultList();

    if (all == null || all.size() == 0){
        return null;
    }else if (all.size() > 1){
        throw new Exception("Unexpected result - "+all.size());
    }else{
        return all.get(0);
    }

respondido 28 nov., 13:22

Este es mi trabajo que funciona. Estoy usando Springboot 1.5.9. No tengo tiempo para identificar la causa raíz. Lo que sé es que esa propiedad anidada se ha ignorado al pasar JacksonMappingAwareSortTranslator. Entonces, lo que hice para solucionar esto es no usar el objeto Ordenar creado por los resolutores. Aquí está mi código en Kotlin. Sin hacer esto, el pageable.sort is null y la clasificación no funciona. Y mi código creará un nuevo PageRequest objeto que tiene un valor no nulo sort eso funciona.

    @RequestMapping("/searchAds", method = arrayOf(RequestMethod.POST))
    fun searchAds(
        @RequestBody cmd: AdsSearchCommand,
        pageable: Pageable,
        resourceAssembler: PersistentEntityResourceAssembler,
        sort: String? = null
    ): ResponseEntity<PagedResources<Resource<Ads>>> {
        val page = adsService.searchAds(cmd, pageable.repairSortIfNeeded(sort))
        resourceAssembler as ResourceAssembler<Ads, Resource<Ads>>
        return adsPagedResourcesAssembler.toResource(page, resourceAssembler).toResponseEntity()
    }

    fun Pageable.repairSortIfNeeded(sort: String?): Pageable {
        return if (sort.isNullOrEmpty() || this.sort != null) {
            this
        } else {
            sort as String
            val sa = sort.split(",")
            val direction = if (sa.size > 1) Sort.Direction.valueOf(sa[1]) else Sort.Direction.ASC
            val property = sa[0]
            PageRequest(this.pageNumber, this.pageSize, direction, property)
        }
    }

Respondido el 02 de junio de 18 a las 13:06

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.