JPA Eclipselink Subquery в предложении where между, CriteriaBuilder и metamodel - PullRequest
1 голос
/ 03 марта 2011

Я хочу сделать этот запрос с метамоделью, но не могу !! Я не знаю, как это сделать.

MYSQL QUERY (с помощью этого запроса я хочу получить все строки из таблицы Clases, которые преподают в данный момент):

SELECT * FROM clases cl 
WHERE CURRENT_TIME() BETWEEN
(SELECT ml2.inicio FROM modulos ml2 WHERE cl.modulo_id=ml2.modulo_id ) AND 
(SELECT ml2.fin FROM modulos ml2 WHERE cl.modulo_id=ml2.modulo_id) AND
 cl.fecha=CURRENT_DATE();

Это мои сущности:

ENTITY MODULOS

@Entity
@Table(name = "modulos")
public class Modulos implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "modulo_id")
    private Integer moduloId;

    @Basic(optional = false)
    @Column(name = "inicio")
    @Temporal(TemporalType.TIME)
    private Date inicio;

    @Basic(optional = false)
    @Column(name = "fin")
    @Temporal(TemporalType.TIME)
    private Date fin;

    @Basic(optional = false)
    @Column(name = "modulo")
    private String modulo;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "modulos")
    private List<GruposHorarioHasModulos> gruposHorarioHasModulosList;

    //getters and setters...
}

КЛАСС ЭНИТИ

@Entity
@Table(name = "clases")
public class Clases implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "clase_id")
    private Integer claseId;

    @Basic(optional = false)
    @Column(name = "aula")
    private String aula;

    @Basic(optional = false)
    @Column(name = "fusion")
    private boolean fusion = false;

    @Basic(optional = false)
    @Column(name = "clase_numero")
    private Integer claseNumero;

    @Basic(optional = false)
    @Column(name = "clase_impartida")
    private boolean claseImpartida = false;

    @JoinColumn(name = "modulo_id", referencedColumnName = "modulo_id")
    @ManyToOne(optional = false)
    private Modulos modulos;

    //getters and setters...
}

У меня есть это:

EntityManager em1 = Persistence.createEntityManagerFactory("myPU").createEntityManager();
CriteriaBuilder cb = em1.getCriteriaBuilder();
CriteriaQuery cq = cb.createQuery();
Root<Clases> root = cq.from(Clases.class);
cq.select(root.get(Clases_.claseId));

Subquery<Date> sqOne = cq.subquery(Date.class);
Root<Modulos> root2 = sqOne.from(Modulos.class);
sqOne.select(root2.get(Modulos_.inicio));

Subquery<Date> horaInicio = sqOne.select(root2.get(Modulos_.inicio)).where(
        cb.equal(
            root2.get(Modulos_.moduloId),
            root.get(Clases_.modulos).get(Modulos_.moduloId)
            )
        );

Subquery<Date> sqTwo = cq.subquery(Date.class);
Root<Modulos> root3 = sqTwo.from(Modulos.class);
Subquery<Date> horaFin = sqTwo.select(root3.get(Modulos_.fin)).where(
        cb.equal(
            root3.get(Modulos_.moduloId),
            root.get(Clases_.modulos).get(Modulos_.moduloId)
            )
        );

cq.where(cb.between(cb.currentTime(), horaInicio, horaFin));
em1.createQuery(cq).getResultList();

Этот код дает мне следующее исключение:

Исключение в потоке "main" java.lang.ClassCastException: org.eclipse.persistence.internal.jpa.querydef.SubQueryImpl не может быть приведение к org.eclipse.persistence.internal.jpa.querydef.ExpressionImpl

Если я изменю предложение where для этого ...

cq.where(cb.between(cb.currentTime(), new Date(), new Date()));

... это работает, но без моего подзапроса, тогда я вижу, что ошибка возникла из моего подзапроса, но я не знаю почему, если я изменю предложение where для этого ...

cq.where(cb.greaterThan(cb.currentTime(), horaInicio));

... я понял:

SELECT t0.clase_id FROM clases t0, clases t1 WHERE (CURRENT_TIME > (SELECT t2.inicio FROM modulos t3, modulos t2 WHERE ((t2.modulo_id = t3.modulo_id) AND (t3.modulo_id = t0.modulo_id))))

Я вижу, что проблема заключается в 2 подзапросах в предложении Между.

Пожалуйста, мне нужна помощь с этим, я потратил 2 недели на поиски ответа, но ... ничего ... помочь. Я использую JPA 2.0 с Netbeans и EclipseLink с генератором метамоделей и Java 6. Я хочу сделать это с помощью метамоделей и критериев построения и критериев

Как вы видите, мне нужно выполнить подзапрос в предложении where, а в этом предложении where мне нужно сделать between, где у каждого параметра есть подзапрос, например:

SELECT * FROM X WHERE CURRENT_TIME BETWEEN **MY_SUBQUERY_ONE** AND **MY_SUBQUERY_TWO**

1 Ответ

0 голосов
/ 27 апреля 2011

Задержка ответа, но ..

Subquery<Date> sqOne = cq.subquery(Date.class);
Root<Modulos> root2 = sqOne.from(Modulos.class);
sqOne.select(root2.get(Modulos_.inicio));

Subquery<Date> horaInicio = sqOne.select(root2.get(Modulos_.inicio)).where(
    cb.equal(
        root2.get(Modulos_.moduloId),
        root.get(Clases_.modulos).get(Modulos_.moduloId)
    )
);

Не уверен, что вы пытаетесь сделать здесь, и это может или не может быть связано с вашей ошибкой. Вы создаете sqOne и делаете выбор. Затем вы переделываете выбор, заменяя предыдущий и копируете результат в horaInicio. Какова цель этого? Вы можете также пропустить sqOne.select(root2.get(Modulos_.inicio)); и продолжать использовать sqOne вместо horaInicio.

Кроме того, я не уверен, что вы можете смешивать и сопоставлять корни, созданные из разных запросов.

...