我一直在尝试使用带有Criteria Builder的TypedQuery构建一个SQL:
select
a.id,
a.numeroAvisoPagamento,
a.industria_id,
a.varejo_id,
a.dataAvisoPagamento,
a.statusAvisoPagamento,
a.dataUploadArquivo,
a.dataImportacaoArquivo,
a.dataConciliacaoAviso,
count(c.avisoPagamento_id) as qtdeNotas,
from
AvisoPagamento a
left join
LoteAvisoPagamento l
ON l.codigoAviso = a.numeroAvisoPagamento
left join
Cobranca c
ON c.avisoPagamento_id = l.id
where
a.industria_id = ?
and a.varejo_id = ?
and a.numeroAvisoPagamento = ?
and a.dataAvisoPagamento between ? and ?
group by
a.id,
a.numeroAvisoPagamento,
a.numeroAvisoPagamento,
a.industria_id,
a.varejo_id,
a.dataAvisoPagamento,
a.statusAvisoPagamento,
a.dataUploadArquivo,
a.dataImportacaoArquivo,
a.dataConciliacaoAviso
模型
AvisoPagamento
@Entity(name = "AvisoPagamento")
public class AvisoPagamento {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@OneToMany(mappedBy = "avisoPagamento", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private List<CobrancaAvisoPagamento> cobrancas;
@OneToMany(mappedBy = "avisoPagamento", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@OrderBy("dataAcao ASC")
@JsonIgnore(accept={"AvisoPagamentoController.*"})
private List<LogAvisoPagamento> logAvisoPagamento;
}
LoteAvisoPagamento
@Entity(name = "LoteAvisoPagamento")
public class LoteAvisoPagamento {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Column(nullable = false)
private Long codigoAviso;
}
Cobranca
public class Cobranca {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@ManyToOne(fetch = FetchType.LAZY, optional = true)
@JoinColumn(name = "avisoPagamento_id")
@JsonIgnore(accept = { "CobrancaLoteController.listaCobrancas", "CobrancaAdmController.*",
"ConciliacaoController.*", "CobrancaIndController.*" })
private LoteAvisoPagamento avisoPagamento;
}
我有两个问题:
我想将这个SQL重新编写为TypedQuery和CriteriaBuilder,所以我尝试了这个:
//Create Criteria Builder
final CriteriaBuilder builder = manager.getCriteriaBuilder();
//Create CriteriaQuery da Classe AvisoPagamento
final CriteriaQuery<AvisoPagamento> query = builder.createQuery(AvisoPagamento.class);
//Create from
final Root<AvisoPagamento> rootAviso = query.from(AvisoPagamento.class);
//Left Join Lote Aviso Pagamento
Root<LoteAvisoPagamento> rootLoteAviso = query.from(LoteAvisoPagamento.class);
final Predicate predicateLeftJoin = builder.equal(rootAviso.get("numeroAvisoPagamento"), rootLoteAviso.get("codigoAviso"));
//Conditions
Predicate predicateAvisoPagamento = builder.and();
//Join Selects
Predicate criteria = builder.conjunction();
criteria = builder.and(criteria, predicateAvisoPagamento);
criteria = builder.and(criteria, predicateLeftJoin);
//Passou a Industria
if (industria != null){
predicateAvisoPagamento = builder.and(predicateAvisoPagamento, builder.equal(rootAviso.get("industria"), industria));
}
//Passou o Varejo
if (varejo != null){
predicateAvisoPagamento = builder.and(predicateAvisoPagamento, builder.equal(rootAviso.get("varejo"), varejo));
}
//Passou o numero do Aviso
if (numeroAviso != null){
predicateAvisoPagamento = builder.and(predicateAvisoPagamento, builder.equal(rootAviso.get("numeroAvisoPagamento"), numeroAviso));
}
//Passou as Datas De e Ate
if (dataDe != null && dataAte != null){
predicateAvisoPagamento = builder.between(rootAviso.<Date>get("dataAvisoPagamento"), dataDe , dataAte);
}
//TypedQuery eh mais robusto, a checagem de tipo é feito na compilacao, eliminando alguns
//tipos de erros
final TypedQuery<AvisoPagamento> typedQuery = manager.createQuery(
query.select(rootAviso).distinct(true)
.where( criteria )
.orderBy(builder.desc(rootAviso.get("dataConciliacaoAviso")))
);
//return List
final List<AvisoPagamento> results = typedQuery.getResultList();
return results;
然后JPA生成了这个SQL:
select
distinct avisopagam0_.id as id1_9_,
avisopagam0_.arquivoFisico as arquivoF2_9_,
avisopagam0_.dataAvisoPagamento as dataAvis3_9_,
avisopagam0_.dataConciliacaoAviso as dataConc4_9_,
avisopagam0_.dataImportacaoArquivo as dataImpo5_9_,
avisopagam0_.dataUploadArquivo as dataUplo6_9_,
avisopagam0_.industria_id as industri9_9_,
avisopagam0_.numeroAvisoPagamento as numeroAv7_9_,
avisopagam0_.statusAvisoPagamento as statusAv8_9_,
avisopagam0_.usuario_id as usuario10_9_,
avisopagam0_.varejo_id as varejo_11_9_
from
AvisoPagamento avisopagam0_ cross
join
LoteAvisoPagamento loteavisop1_
where
1=1
and 1=1
and avisopagam0_.numeroAvisoPagamento=loteavisop1_.codigoAviso
order by dataAvisoPagamento desc
如何使用TypedQuery计算Table Cobranca中的记录以及如何解决此问题:
where
1=1
and 1=1
很奇怪,我已经阅读了很多关于TypedQuery的内容,但我已经被卡住了
答案 0 :(得分:0)
我认为 ON 子句仅适用于JPA 2.1版本中的关系。
所以直到现在你都不能使用
联合两栏:ON LoteAvisoPagamento.codigoAviso = AvisoPagamento.numeroAvisoPagamento
因为JPA 2.1(上一版本)不支持。
因此它不适用于Criteria或JPQL
注意: CROSS JOIN 不需要 ON 子句,这就是为什么你在生成的查询中看到它也不能LEFT JOIN in 你用这种方式的标准(不可能)它总会如此 生成为CROSS JOIN
INNER JOIN和LEFT JOIN需要实体之间的关系
请尝试下一个JPQL,并测试它是否有效(我认为它不起作用),它很简单但它应该与你想要的类似(至少类似)在一个条件,直到现在)
SELECT aviso.id, aviso.numeroAvisoPagamento, loteAviso.id
FROM AvisoPagamento aviso
LEFT JOIN LoteAvisoPagamento loteAviso
ON loteAviso.codigoAviso = aviso.numeroAvisoPagamento
WHERE aviso.numeroAvisoPagamento = :numeroAviso
将:numeroAviso 替换为任何有效值,然后将其测试为entityManager.createQuery(此处放置查询)
无论如何,我测试了我的不同实体,但逻辑相同,我得到了一个例外,因为我预期
注意:我正在使用 JPA 与 Hibernate 提供商
这是我得到的例外
引起:org.hibernate.hql.internal.ast.QuerySyntaxException:期望加入的路径!
所以它期待类似的东西(你的实体不支持)
LEFT JOIN aviso.loteAvisoPagamento loteAviso
在下一个查询中
SELECT aviso.id, aviso.numeroAvisoPagamento, loteAviso.id
FROM AvisoPagamento aviso
LEFT JOIN aviso.loteAvisoPagamento loteAviso
ON loteAviso.codigoAviso = aviso.numeroAvisoPagamento
WHERE aviso.numeroAvisoPagamento = :numeroAviso
答案 1 :(得分:0)
正如@ mibrahim.iti告诉LEFT JOIN或INNER需要实体之间的关系所以我使用Native SQL来做这个,这是我的最终解决方案:
//Sql Log
final StringBuilder sqlLog = new StringBuilder();
sqlLog.append("select l from LogAvisoPagamento l where l.avisoPagamento.id = :idAviso order by l.dataAcao ");
final Query queryLog = manager.createQuery(sqlLog.toString());
//Sql Aviso
final StringBuilder sql = new StringBuilder();
sql.append("select a.id, ")
.append(" a.numeroAvisoPagamento, ")
.append(" a.industria_id, ")
.append(" a.varejo_id, ")
.append(" a.dataAvisoPagamento, ")
.append(" a.statusAvisoPagamento, ")
.append(" a.dataUploadArquivo, ")
.append(" a.dataImportacaoArquivo, ")
.append(" a.dataConciliacaoAviso, ")
.append(" count(c.avisoPagamento_id) as qtdeNotas, ")
.append(" r.valorTotalBruto ")
.append(" from AvisoPagamento a ")
.append(" left join ResumoAvisoPagamento r ON r.avisoPagamento_id = a.id ")
.append(" left join LoteAvisoPagamento l ON l.codigoAviso = a.numeroAvisoPagamento")
.append(" left join Cobranca c ON c.avisoPagamento_id = l.id");
boolean where = false;
//Passou a Industria
if (industria != null){
sql.append(" where a.industria_id = :idIndustria");
where = true;
}
//Passou o Varejo
if (varejo != null){
if (!where){
sql.append(" where a.varejo_id = :idVarejo");
where = true;
}else{
sql.append(" and a.varejo_id = :idVarejo");
}
}
//Passou o numero do Aviso
if (numeroAviso != null){
if (!where){
sql.append(" where a.numeroAvisoPagamennto = :numeroAvisoPagamento");
where = true;
}else{
sql.append(" and a.numeroAvisoPagamento = :numeroAvisoPagamento");
}
}
//Passou as Datas De e Ate
if (dataDe != null && dataAte != null){
if (!where){
where = true;
sql.append(" where a.dataAvisoPagamento between :dataDe and :dataAte");
}else{
sql.append(" and a.dataAvisoPagamento between :dataDe and :dataAte");
}
}
sql.append(" group by a.id, a.numeroAvisoPagamento, ")
.append(" a.numeroAvisoPagamento, ")
.append(" a.industria_id, ")
.append(" a.varejo_id, ")
.append(" a.dataAvisoPagamento, ")
.append(" a.statusAvisoPagamento, ")
.append(" a.dataUploadArquivo, ")
.append(" a.dataImportacaoArquivo, ")
.append(" a.dataConciliacaoAviso, ")
.append(" r.valorTotalBruto ");
final Query query = manager.createNativeQuery(sql.toString());
//Passou a Industria
if (industria != null){
query.setParameter("idIndustria", industria.getId());
}
//Passou o Varejo
if (varejo != null){
query.setParameter("idVarejo", varejo.getId());
}
//Passou o numero do Aviso
if (numeroAviso != null){
query.setParameter("numeroAvisoPagamento", numeroAviso);
}
//Passou as Datas De e Ate
if (dataDe != null && dataAte != null){
query.setParameter("dataDe", dataDe);
query.setParameter("dataAte", dataAte);
}
final List<AvisoPagamento> avisosPagamentos = new ArrayList<AvisoPagamento>();
//Percorrendo os Registros
for (final Object array : query.getResultList()){
final Object[] arrayAviso = (Object[]) array;
final ResumoAvisoPagamento resumo = new ResumoAvisoPagamento();
resumo.setValorTotalBruto((BigDecimal) arrayAviso[10]);
final AvisoPagamento avisoPagamento = new AvisoPagamento();
final BigInteger id = new BigInteger(arrayAviso[0].toString());
avisoPagamento.setId(id.longValue());
avisoPagamento.setNumeroAvisoPagamento((String) arrayAviso[1]);
avisoPagamento.setDataAvisoPagamento((Date) arrayAviso[4]);
avisoPagamento.setStatusAvisoPagamento(StatusAvisoPagamento.valueOf(arrayAviso[5].toString()));
avisoPagamento.setDataUploadArquivo((Date) arrayAviso[6]);
avisoPagamento.setDataImportacaoArquivo((Date) arrayAviso[7]);
avisoPagamento.setDataConciliacaoAviso((Date) arrayAviso[8]);
final BigInteger qtde = new BigInteger(arrayAviso[9].toString());
avisoPagamento.setQtdeNotas(qtde.intValue());
queryLog.setParameter("idAviso", avisoPagamento.getId());
//Get Log
final List<LogAvisoPagamento> logs = queryLog.getResultList();
avisoPagamento.setLogAvisoPagamento(logs);
avisoPagamento.setResumoAvisoPagamento(resumo);
avisosPagamentos.add(avisoPagamento);
}
return avisosPagamentos;