JPA Eclipselink子查询在where子句之间,CriteriaBuilder和元模型
Posted
技术标签:
【中文标题】JPA Eclipselink子查询在where子句之间,CriteriaBuilder和元模型【英文标题】:JPA Eclipselink Subquery in where clause with between, CriteriaBuilder and metamodel 【发布时间】:2011-03-03 19:19:20 【问题描述】:我想用元模型做这个查询,但我做不到!!我不知道该怎么做。
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
@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();
这段代码给了我以下异常:
线程“主”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))))
我可以看到问题是 between 子句中的 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】:稍晚回答但是..
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。
另外,我不确定您是否可以混合和匹配从不同查询创建的根。
【讨论】:
以上是关于JPA Eclipselink子查询在where子句之间,CriteriaBuilder和元模型的主要内容,如果未能解决你的问题,请参考以下文章
Mysql查询详解(条件查询、子查询、模糊查询、连接查询。。。)
Windows 7中的JPA Eclipselink查询解析问题
使用 IN 语句的 Eclipselink JPA 类型安全查询