Запрос критериев JPA загружает всю таблицу

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

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;

@Entity
@Table(name="DEMO_VARIABLES")
public class Variable implements Serializable
{
    private static final long serialVersionUID = -1734898766626582592L;

    @Id
    @SequenceGenerator(name="VARIABLE_ID_GENERATOR", sequenceName="DEMO_VARIABLE_ID_SEQ", allocationSize=1)
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="VARIABLE_ID_GENERATOR")
    @Column(name="VARIABLE_ID", unique=true, nullable=false, precision=22)
    private long variableId;

    @Column(name="VARIABLE_NAME", nullable=false, length=50)
    private String variableName;

    @Column(name="VARIABLE_VALUE", nullable=false, length=500)
    private String variableValue;

    public Variable()
    {

    }

    public long getVariableId()
    {
        return variableId;
    }

    public void setVariableId(long variableId)
    {
        this.variableId = variableId;
    }

    public String getVariableName()
    {
        return variableName;
    }

    public void setVariableName(String variableName)
    {
        this.variableName = variableName;
    }

    public String getVariableValue()
    {
        return variableValue;
    }

    public void setVariableValue(String variableValue)
    {
        this.variableValue = variableValue;
    }
}

Теперь я хочу использовать запрос критериев для загрузки всей таблицы (т.е. "выбрать * из переменных"). Я хотел бы использовать запрос критериев больше для согласованности кода, чем что-либо еще. Я получаю это исключение, хотя:

java.lang.IllegalStateException: No criteria query roots were specified
    at org.hibernate.ejb.criteria.CriteriaQueryImpl.validate(CriteriaQueryImpl.java:303)
    at org.hibernate.ejb.criteria.CriteriaQueryCompiler.compile(CriteriaQueryCompiler.java:145)
    at org.hibernate.ejb.AbstractEntityManagerImpl.createQuery(AbstractEntityManagerImpl.java:437

Я использую следующий запрос:

public List<Variable> loadAllVariables()
{
    CriteriaBuilder builder = em.getCriteriaBuilder();
    CriteriaQuery<Variable> query = builder.createQuery(Variable.class);

    return em.createQuery(query).getResultList();
} 

Я знаю, что исключение означает, что оно хочет этого:

Root<Variable> variableRoot = query.from(Variable.class);

Но без предиката я не понимаю, как получить корневой объект в запросе?


person Greg    schedule 26.07.2012    source источник


Ответы (2)


Я не уверен, правильно ли я вас понял, но если цель состоит в том, чтобы выбрать список извлечения всех объектов Variable, то можно пойти следующим путем:

public List<Variable> loadAllVariables() {
    CriteriaBuilder builder = em.getCriteriaBuilder();
    CriteriaQuery<Variable> query = builder.createQuery(Variable.class);
    Root<Variable> variableRoot = query.from(Variable.class);
    query.select(variableRoot);

    return em.createQuery(query).getResultList();
} 

Разница в том, что используется select. Все реализации не используют неявно последний вызов from вместо select. В спецификации JPA 2.0 это сказано следующим образом:

Переносимые приложения должны использовать метод select или multiselect для указания списка выбора запроса. Приложения, не использующие один из этих методов, не будут переносимыми.

person Mikko Maunu    schedule 26.07.2012
comment
Спасибо, это сработало. Я был знаком только с использованием query.where() и присвоением ему Predicated на основе корня. query.select() был недостающей ссылкой. - person Greg; 26.07.2012

Работать с запросом и его корнем очень просто:
Сначала получите корень так, как вы описали:

Root<Variable> variableRoot = query.from(Variable.class);

После этого вы должны сообщить запросу, что он должен делать с корнем: в данном случае выбрать.

query.select(variableRoot);

После этого вы можете изменить запрос с помощью функции query.where(...) и т.п. Когда вы закончите, вы готовы запустить его со своим

return em.createQuery(query).getResultList();

Дополнительные сведения см. в руководстве по Oracle.

person Humungus    schedule 26.07.2012