为什么 JPQL 生成的查询与原始查询不同
Why JPQL generated query differs from original
我正在审查这样的 JPQL 查询:
SELECT SELECT SUM( func('NVL', l.prim_emiti_ced_periodo, 0)
+ func('NVL', l.prim_dev_n_emiti_ced_fin, 0)
- func('NVL', l.prim_dev_n_emiti_ced_ini, 0))
primas_cedidas_netas,
SUM( func('NVL', l.com_prim_emiti_ced_periodo, 0)
+ func('NVL', l.com_prim_dev_n_emiti_ced_fin, 0)
- func('NVL', l.com_prim_dev_n_emiti_ced_ini, 0))
gastos_reintegrados,
SUM (func('NVL', l.reaj_com_segun_siniestralidad, 0))
reajustes_gastos_reintegrados,
SUM (func('NVL', l.prest_gastos_pagados_ced, 0)) siniestros_pagados,
SUM (func('NVL', l.recobros_cedidos, 0)) siniestros_recobrados,
SUM (func('NVL', l.deposito_sobre_prim_fin, 0)) deposito_retenido_a_X,
SUM (func('NVL', l.deposito_sobre_prim_ini, 0)) deposito_reembolsado,
SUM(func('NVL', l.prim_dev_n_emiti_ced_fin, 0)
+ func('NVL', l.prim_emiti_ced_pend_cob_fin, 0))
primas_pend_cobro_a_X,
SUM (func('NVL', l.detrac_sobre_deposito_prim_fin, 0))
detraccion_depo_retenido,
SUM(func('NVL', l.com_prim_dev_n_emiti_ced_fin, 0)
+ func('NVL', l.com_prim_emit_ce_pedte_cob_fin, 0))
gasto_reinteg_s_pp,
SUM(func('NVL', l.prim_dev_n_emiti_ced_ini, 0)
+ func('NVL', l.prim_emiti_ced_pend_cob_ini, 0))
primas_pdte_cobro_cta_anterior,
SUM (func('NVL', l.detrac_sobre_deposito_prim_ini, 0))
detraccion_depo_ret_s_ppc_ant,
SUM(func('NVL', l.com_prim_dev_n_emiti_ced_ini, 0)
+ func('NVL', l.com_prim_emit_ce_pedte_cob_ini, 0))
gasto_reinteg_s_pp_cta_anterior,
SUM (func('NVL', l.intereses_deposito, 0)) intereses_s_depo_reemb,
SUM (func('NVL', l.participacion_beneficios, 0)) participacion_beneficios,
SUM (func('NVL', l.participacion_perdidas, 0)) participacion_perdidas,
AVG(cc.porcentaje_participacion) porcentaje_participacion,
AVG(c.porcCesGralIni) porcCesGralIni,
SUM (func('NVL', l.saldo_cuenta_efec_cp, 0) + func('NVL', l.depos_sobre_siniest_pdtes_fin, 0) - func('NVL', l.depos_sobre_siniest_pdtes_ini, 0) ) saldo_cuenta_efec_cp,
SUM (func('NVL', l.depos_sobre_siniest_pdtes_fin, 0) ) deposito_retenido_a_X_sin,
SUM (func('NVL', l.depos_sobre_siniest_pdtes_ini, 0) ) deposito_reembolsado_sin
FROM LiquidacionCpReaseg l, ContratoComun c, ContratoCorredor cc
WHERE l.id.pais = c.pais.id
AND l.id.compania = c.compania.id
AND l.id.tipo_contrato = c.tipoContrato.id
AND l.id.producto = c.producto
AND l.id.reasegurador = c.reasegurador.id
AND l.id.anio_suscripcion = c.anyo
AND c.id = cc.id.id_contrato
AND l.id.trimestre=:trimestre
AND l.id.anio_suscripcion=:anio
AND l.producto.id.tipoProducto IN:tiposProducto
AND l.id.pais IN :paises
AND l.id.compania = :compania
AND l.corredor.id = cc.corredor.id
AND l.id.reasegurador=:id AND l.corredor.id=:identificadorCorredor
问题是,如果我记录生成的查询,它在 FROM
和 WHERE
投影中有所不同:
FROM Corredor t9,
Corredor t8,
PRODUCTO t7,
Reasegurador t6,
TIPO_CONTRATO t5,
COMPANIA t4,
PAIS t3,
CONTRATO_COMUN t2,
CONTRATO_CORREDOR t1,
LIQUIDACIONES_CP_REASEG t0
WHERE ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (t0.pais = t3.id_pais)
AND (t0.compania = t4.id_compania))
AND (t0.tipo_contrato =
t5.id_tipo_contrato))
AND (t0.producto = t2.producto))
AND (t0.reasegurador = t6.id_reasegurador))
AND (t0.anio_suscripcion = t2.anyo))
AND (t2.id_contrato = t1.id_contrato))
AND (t0.trimestre = 201506))
AND (t0.anio_suscripcion = 1991))
AND (t7.tipo_producto IN (1)))
AND (t0.pais IN (116)))
AND (t0.compania = 1))
AND (t8.id_corredor = t9.id_corredor))
AND (t0.reasegurador = 1))
AND (t0.corredor = 0))
AND ( ( ( ( ( ( (t3.id_pais = t2.pais)
AND (t4.id_compania = t2.compania))
AND (t5.id_tipo_contrato = t2.tipo_contrato))
AND (t6.id_reasegurador = t2.reasegurador))
AND ( (t7.tipo_producto = t0.producto)
AND ( (t7.compania = t0.compania)
AND (t7.pais = t0.pais))))
AND (t8.id_corredor = t0.corredor))
AND (t9.id_corredor = t1.id_corredor)))
项目正在使用 EclipseLink 2.2.0
和 Oracle11
数据库。使用 SpringRoo
生成实体
查询是这样生成的:
TypedQuery<Object[]> q =entityManager.createQuery(jpql+sFiltroCorredorResasegurador,Object[].class);
...
return q.getSingleResult();`
已编辑答案
我在您的 select 部分中没有看到任何会导致访问 ManyToOne 引用的内容。
您还尝试延迟获取这些引用,这并没有改变任何东西。
因此,剩下的就是 Where 部分。这就是我之前回答您时忽略的内容。
例如,table PAIS 被添加到 where SQL 中,因为在 JPQL 中有一个 Where 术语 l.id.pais = c.pais.id
。
我敢打赌,在 ContratoComun 中有一个 ManyToOne 参考 pais。
c.pais.id
会解析为:加载c.pais引用的PAIS的实体,然后使用c.pais的属性id
加载到 select 的实体应该引用 "ContratoComun"。这只是一个非常复杂的例子的一部分
但我认为其他参考资料也可以用同样的方式解释。
旧的已过时的答案
如果你的意思是 "Why are there more tables in the from clause then classes in the jpa from clause" 那么,(不知道你的 class 定义)我猜你使用例如manyToOne 对其他 class 的引用,例如"PRODUCTO".
我不知道你的完整 select 部分。但我认为实体管理器出于某种原因试图从引用的对象中添加字段。添加了额外的 where 项以匹配 ManyToOne 对象的外键。
我找到了解决方案。问题是他们试图将 FK 字段与不相关的表进行比较,即:
l.id.compania = c.compania.id
因此 c.compania
是 ManyToOne
映射到 Compania
类型,JPQL 加入 c
和 Compania
在生成的 sql。
对于这种情况,需要将 FK 映射为简单列以避免连接到 Compania
:
@Column(name = "compania",updatable=false,insertable=false)
private BigDecimal compania_id;
并将查询更改为:
l.id.compania = c.compania_id
我正在审查这样的 JPQL 查询:
SELECT SELECT SUM( func('NVL', l.prim_emiti_ced_periodo, 0)
+ func('NVL', l.prim_dev_n_emiti_ced_fin, 0)
- func('NVL', l.prim_dev_n_emiti_ced_ini, 0))
primas_cedidas_netas,
SUM( func('NVL', l.com_prim_emiti_ced_periodo, 0)
+ func('NVL', l.com_prim_dev_n_emiti_ced_fin, 0)
- func('NVL', l.com_prim_dev_n_emiti_ced_ini, 0))
gastos_reintegrados,
SUM (func('NVL', l.reaj_com_segun_siniestralidad, 0))
reajustes_gastos_reintegrados,
SUM (func('NVL', l.prest_gastos_pagados_ced, 0)) siniestros_pagados,
SUM (func('NVL', l.recobros_cedidos, 0)) siniestros_recobrados,
SUM (func('NVL', l.deposito_sobre_prim_fin, 0)) deposito_retenido_a_X,
SUM (func('NVL', l.deposito_sobre_prim_ini, 0)) deposito_reembolsado,
SUM(func('NVL', l.prim_dev_n_emiti_ced_fin, 0)
+ func('NVL', l.prim_emiti_ced_pend_cob_fin, 0))
primas_pend_cobro_a_X,
SUM (func('NVL', l.detrac_sobre_deposito_prim_fin, 0))
detraccion_depo_retenido,
SUM(func('NVL', l.com_prim_dev_n_emiti_ced_fin, 0)
+ func('NVL', l.com_prim_emit_ce_pedte_cob_fin, 0))
gasto_reinteg_s_pp,
SUM(func('NVL', l.prim_dev_n_emiti_ced_ini, 0)
+ func('NVL', l.prim_emiti_ced_pend_cob_ini, 0))
primas_pdte_cobro_cta_anterior,
SUM (func('NVL', l.detrac_sobre_deposito_prim_ini, 0))
detraccion_depo_ret_s_ppc_ant,
SUM(func('NVL', l.com_prim_dev_n_emiti_ced_ini, 0)
+ func('NVL', l.com_prim_emit_ce_pedte_cob_ini, 0))
gasto_reinteg_s_pp_cta_anterior,
SUM (func('NVL', l.intereses_deposito, 0)) intereses_s_depo_reemb,
SUM (func('NVL', l.participacion_beneficios, 0)) participacion_beneficios,
SUM (func('NVL', l.participacion_perdidas, 0)) participacion_perdidas,
AVG(cc.porcentaje_participacion) porcentaje_participacion,
AVG(c.porcCesGralIni) porcCesGralIni,
SUM (func('NVL', l.saldo_cuenta_efec_cp, 0) + func('NVL', l.depos_sobre_siniest_pdtes_fin, 0) - func('NVL', l.depos_sobre_siniest_pdtes_ini, 0) ) saldo_cuenta_efec_cp,
SUM (func('NVL', l.depos_sobre_siniest_pdtes_fin, 0) ) deposito_retenido_a_X_sin,
SUM (func('NVL', l.depos_sobre_siniest_pdtes_ini, 0) ) deposito_reembolsado_sin
FROM LiquidacionCpReaseg l, ContratoComun c, ContratoCorredor cc
WHERE l.id.pais = c.pais.id
AND l.id.compania = c.compania.id
AND l.id.tipo_contrato = c.tipoContrato.id
AND l.id.producto = c.producto
AND l.id.reasegurador = c.reasegurador.id
AND l.id.anio_suscripcion = c.anyo
AND c.id = cc.id.id_contrato
AND l.id.trimestre=:trimestre
AND l.id.anio_suscripcion=:anio
AND l.producto.id.tipoProducto IN:tiposProducto
AND l.id.pais IN :paises
AND l.id.compania = :compania
AND l.corredor.id = cc.corredor.id
AND l.id.reasegurador=:id AND l.corredor.id=:identificadorCorredor
问题是,如果我记录生成的查询,它在 FROM
和 WHERE
投影中有所不同:
FROM Corredor t9,
Corredor t8,
PRODUCTO t7,
Reasegurador t6,
TIPO_CONTRATO t5,
COMPANIA t4,
PAIS t3,
CONTRATO_COMUN t2,
CONTRATO_CORREDOR t1,
LIQUIDACIONES_CP_REASEG t0
WHERE ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (t0.pais = t3.id_pais)
AND (t0.compania = t4.id_compania))
AND (t0.tipo_contrato =
t5.id_tipo_contrato))
AND (t0.producto = t2.producto))
AND (t0.reasegurador = t6.id_reasegurador))
AND (t0.anio_suscripcion = t2.anyo))
AND (t2.id_contrato = t1.id_contrato))
AND (t0.trimestre = 201506))
AND (t0.anio_suscripcion = 1991))
AND (t7.tipo_producto IN (1)))
AND (t0.pais IN (116)))
AND (t0.compania = 1))
AND (t8.id_corredor = t9.id_corredor))
AND (t0.reasegurador = 1))
AND (t0.corredor = 0))
AND ( ( ( ( ( ( (t3.id_pais = t2.pais)
AND (t4.id_compania = t2.compania))
AND (t5.id_tipo_contrato = t2.tipo_contrato))
AND (t6.id_reasegurador = t2.reasegurador))
AND ( (t7.tipo_producto = t0.producto)
AND ( (t7.compania = t0.compania)
AND (t7.pais = t0.pais))))
AND (t8.id_corredor = t0.corredor))
AND (t9.id_corredor = t1.id_corredor)))
项目正在使用 EclipseLink 2.2.0
和 Oracle11
数据库。使用 SpringRoo
查询是这样生成的:
TypedQuery<Object[]> q =entityManager.createQuery(jpql+sFiltroCorredorResasegurador,Object[].class);
...
return q.getSingleResult();`
已编辑答案
我在您的 select 部分中没有看到任何会导致访问 ManyToOne 引用的内容。 您还尝试延迟获取这些引用,这并没有改变任何东西。 因此,剩下的就是 Where 部分。这就是我之前回答您时忽略的内容。
例如,table PAIS 被添加到 where SQL 中,因为在 JPQL 中有一个 Where 术语 l.id.pais = c.pais.id
。
我敢打赌,在 ContratoComun 中有一个 ManyToOne 参考 pais。
c.pais.id
会解析为:加载c.pais引用的PAIS的实体,然后使用c.pais的属性id
加载到 select 的实体应该引用 "ContratoComun"。这只是一个非常复杂的例子的一部分
但我认为其他参考资料也可以用同样的方式解释。
旧的已过时的答案
如果你的意思是 "Why are there more tables in the from clause then classes in the jpa from clause" 那么,(不知道你的 class 定义)我猜你使用例如manyToOne 对其他 class 的引用,例如"PRODUCTO".
我不知道你的完整 select 部分。但我认为实体管理器出于某种原因试图从引用的对象中添加字段。添加了额外的 where 项以匹配 ManyToOne 对象的外键。
我找到了解决方案。问题是他们试图将 FK 字段与不相关的表进行比较,即:
l.id.compania = c.compania.id
因此 c.compania
是 ManyToOne
映射到 Compania
类型,JPQL 加入 c
和 Compania
在生成的 sql。
对于这种情况,需要将 FK 映射为简单列以避免连接到 Compania
:
@Column(name = "compania",updatable=false,insertable=false)
private BigDecimal compania_id;
并将查询更改为:
l.id.compania = c.compania_id