Hello, I've assembled the following class Specification:
public class ItemVendedorSpecification implements Specification<ItemVendedor> {
private static final long serialVersionUID = 1L;
@Autowired
CategoriaRepository categoriaRepository;
@Autowired
FabricanteRepository fabricanteRepository;
@Autowired
VendedorRepository vendedorRepository;
private String descricao;
private List<Long> categorias;
private List<Long> fabricantes;
private List<Long> vendedores;
List<Predicate> predicates = new ArrayList<>();
public ItemVendedorSpecification(String descricao, List<Long> categorias, List<Long> fabricantes, List<Long> vendedores) {
super();
this.descricao = descricao;
this.categorias = categorias;
this.fabricantes = fabricantes;
this.vendedores = vendedores;
}
@Override
public Predicate toPredicate(Root<ItemVendedor> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
if (!descricao.isEmpty()) {
String PalavraChave[] = descricao.split(" ");
for (String filtro : PalavraChave) {
predicates.add(builder.like(builder.upper(root.get("id").get("produto").get("descricaoDetalhada")), "%" + filtro.toUpperCase() + "%"));
}
}
predicates.add(builder.isTrue(root.get("disponivel")));
if(!fabricantes.isEmpty()) {
predicates.add(root.get("id").get("produto").get("fabricante").get("id").in(fabricantes));
}
if(!vendedores.isEmpty()) {
predicates.add(root.get("id").get("vendedor").get("id").in(vendedores));
}
if(!categorias.isEmpty()) {
predicates.add(root.join("id").get("produto").get("categorias").get("id").in(categorias));
}
return builder.and(predicates.toArray(new Predicate[1]));
}
}
Almost all of the predicates are working, except the one that inserts the category criteria. It's not working and I'm having a hard time creating it.
In the way that it is returning the following error:
"Illegal attempt to dereference path source [null.produto.categorias] of basic type; nested exception is java.lang.IllegalStateException: Illegal attempt to dereference path source [null.produto.categorias] of basic type",
Can anyone help me in developing this if?
Below the detail of the ItemSeller class:
public class ItemVendedor implements Serializable{
private static final long serialVersionUID = 1L;
private ItemVendedorPK id = new ItemVendedorPK();
private BigDecimal preco;
private Boolean disponivel;
private Date dt_insert;
private Date dt_update;
private BigDecimal desconto;
public ItemVendedor() {
}
public ItemVendedor(Produto produto, Vendedor vendedor, BigDecimal preco, BigDecimal desconto ,Boolean disponivel) {
super();
this.id.setProduto(produto);
this.id.setVendedor(vendedor);
this.preco = preco;
this.disponivel = disponivel;
this.desconto = desconto;
}
//GETs and SETs
As you can see, it has a field called id that is a key made up of the Vendedor vendedor
and Produto produto
fields.
Within the Product class I have a List<Categoria> categorias
. Because a product can belong to several categories.
In turn, the Category class has id
.
What I want to put in Specification
, is a way to search all ItemVendedor
that have within their list of categories some category that I quoted as a parameter in another list List<Long> categorias
.
Personal, I am putting some more information to simplify understanding, below is a simplified class diagram to understand the context of the situation:
As you can see in the Product class a product can have several categories, and one category may have several products.
What I intend to do is the following: I want to give a list of values of type Long that refer to category codes. This parameter is passed through a list ( List<Long> categoriasId
) and will be used in the following query:
I want you to return all objects of type Vendor, where the list of product categories has at least 1 item that is within the last parameter list.
This approach is being done through Specification because it is a dynamic query, which will aggregate other criteria according to the class code.
Sincerely.