Product displayed is the smallest within the group (Criteria)

Asked

Viewed 92 times

3

I have a function in the system that I am developing that returns a list of lots in which the batch quantity is greater than zero, searching for the product name (foreign key). Up to this point I got it. When doing the search it returns me all the batches of that product that I typed the name.

However I have several lots of the same product, I wanted to perform a filter so that only be displayed the lot that the validity is the smallest among them, locking the option of the user to choose a lot of the product, and that has another that the validity is smaller and could be released soon.

public List<Lote> lotePorNomeMedicamento(String nome) {
    Session session = this.manager.unwrap(Session.class);

    Criteria criteria = session.createCriteria(Lote.class)
            // fazemos uma associação (join) com medicamento e nomeamos como "m"
            .createAlias("medicamento", "m");

    // acessamos o nome do medicamento associado ao pedido pelo alias "m",
    // criado anteriormente
    criteria.add(Restrictions.ilike("m.nome", nome, MatchMode.ANYWHERE));

    // retringir lotes com quantidade zero
    criteria.add(Restrictions.gt("quantidade",0));

    // restringir lotes para o valor exibido seja o menor do grupo
    criteria.add(Restrictions.gt("validade", value))


    return criteria.addOrder(Order.asc("lote")).list();
}

This is the code thought to use Restrictions.gt in validity, but the value of this validity has to be the lowest among the three.

Ex:

(Lot - Product - Validity - Quantity)

Lote01 - Product01 - 01/02/2016 - 10

Lote02 - Product01 - 02/03/2016 - 10

Lote03 - Product01 - 08/02/2016 - 10

The result that would be displayed would be Lote01 only, as it is batch of the same product that the validity is the least among them. Any suggestions? It is possible to do this using Criteria?

Batch class

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Transient;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;

import org.hibernate.validator.constraints.NotBlank;
@Entity
@Table (name = "lote")
public class Lote implements Serializable {

private static final long serialVersionUID = 1L;

private String lote;
private String marca;
private Integer quantidade;
private Date validade;
private Medicamento medicamento;
@SuppressWarnings("unused")
private String lotePesq;

@NotBlank
@Id
public String getLote() {
    return lote;
}

public void setLote(String lote) {
    this.lote = lote;
}

@NotBlank
public String getMarca() {
    return marca;
}

public void setMarca(String marca) {
    this.marca = marca;
}

@Min(value = 0, message = "deve ser maior que zero.")
public Integer getQuantidade() {
    return quantidade;
}

public void setQuantidade(Integer quantidade) {
    this.quantidade = quantidade;
}

@NotNull
public Date getValidade() {
    return validade;
}

public void setValidade(Date validade) {
    this.validade = validade;
}

@NotNull
@ManyToOne
public Medicamento getMedicamento() {
    return medicamento;
}

public void setMedicamento(Medicamento medicamento) {
    this.medicamento = medicamento;
}   

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((lote == null) ? 0 : lote.hashCode());
    return result;
}

@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    Lote other = (Lote) obj;
    if (lote == null) {
        if (other.lote != null)
            return false;
    } else if (!lote.equals(other.lote))
        return false;
    return true;
}

}

1 answer

2

Do the following

ProjectionList projections = Projections.projectionList();
projections.add(Projections.min("validade"))
criteria.setProjection(projections)
  • I had to use it like this: criteria.add((Criterion) Projections.min("validity")); but this error appears: Caused by: java.lang.Classcastexception: org.hibernate.Criterion.Aggregateprojection cannot be cast to org.hibernate.Criterion.Criterion - I had to cast the cast because it’s required by the code.

  • I edited the code, so it gets more elegant.

  • Changed by your code, but is displaying this error: java.lang.Classcastexception: java.sql.Timestamp cannot be cast to br.com.modelo.Lote - I asked the Lote class how I mapped it. This happens whenever I type each letter of the name, because the field and the autocomplete type of the first faces.

  • This is a type conversion problem, which is outside the scope of the original question. If my answer is correct, please tick it and create another question stating the JSF screen and bean mappings you made. However reading the exception it seems that you are passing a temporal object in place of a lot.

  • I will look for more details on the new problem! And put the solution together with the confirmation of your answer!

  • Your solution apparently did not solve my problem, as it is generating conflict in some way with my conversion class from object to string.

Show 1 more comment

Browser other questions tagged

You are not signed in. Login or sign up in order to post.