Java JPA-带左连接和计数的TypedQuery
我一直在尝试使用TypedQuery和Criteria Builder构建下面的SQL:Java JPA-带左连接和计数的TypedQuery,java,database,hibernate,jpa,hql,Java,Database,Hibernate,Jpa,Hql,我一直在尝试使用TypedQuery和Criteria Builder构建下面的SQL: select a.id, a.numeroAvisoPagamento, a.industria_id, a.varejo_id, a.dataAvisoPagamento, a.statusAvisoPagamento, a.dataUploadArquivo, a.dataIm
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;
}
@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;
}
我有两个问题:
//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;
如何使用TypedQuery计算表Cobranca中的记录,以及如何解决此问题:
where
1=1
and 1=1
奇怪的是,我读了很多关于TypedQuery的书,但我被困在了我认为ON子句只处理JPA2.1版本中的关系 所以到现在为止你还不能用 具有两列的并集:在LoteAvisoPagamento.codigoAviso=AvisoPagamento.numerioavisopagamento上 因为JPA2.1(最新版本)不支持这一点 因此,它在标准或JPQL上不起作用 注意:交叉连接不需要ON子句,这就是为什么您在生成的查询中看到它,而且您也不能执行左连接 你使用的标准(不可能)总是这样 生成为交叉连接 内部联接和左联接需要实体之间的关系 请尝试您的下一个JPQL,并测试它是否有效(我认为它不会起作用),它很简单,但应该与您想要做的类似(至少到目前为止在一个条件下类似) 用任何有效值替换:numerioaviso,然后将其作为entityManager.createQuery进行测试(将查询放在此处) 不管怎样,我在我这边测试了不同的实体,但逻辑相同,我得到了一个异常 注意:我将JPA与Hibernate provider一起使用 这是我得到的例外 原因:org.hibernate.hql.internal.ast.QuerySyntaxException:应加入的路径 所以它期望类似的东西(您的实体不支持) 左连接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
我认为ON条款只适用于JPA2.1版本中的关系 所以到现在为止你还不能用 具有两列的并集:在LoteAvisoPagamento.codigoAviso=AvisoPagamento.numerioavisopagamento上 因为JPA2.1(最新版本)不支持这一点 因此,它在标准或JPQL上不起作用 注意:交叉连接不需要ON子句,这就是为什么您在生成的查询中看到它,而且您也不能执行左连接 你使用的标准(不可能)总是这样 生成为交叉连接 内部联接和左联接需要实体之间的关系 请尝试您的下一个JPQL,并测试它是否有效(我认为它不会起作用),它很简单,但应该与您想要做的类似(至少到目前为止在一个条件下类似) 用任何有效值替换:numerioaviso,然后将其作为entityManager.createQuery进行测试(将查询放在此处) 不管怎样,我在我这边测试了不同的实体,但逻辑相同,我得到了一个异常 注意:我将JPA与Hibernate provider一起使用 这是我得到的例外 原因:org.hibernate.hql.internal.ast.QuerySyntaxException:应加入的路径 所以它期望类似的东西(您的实体不支持) 左连接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
@mibrahim.iti告诉左边的JOIN或internal需要实体之间的关系,所以我使用本机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;
//Sql日志
最终StringBuilder sqlLog=新StringBuilder();
append(“从LogAvisoPagamento l中选择l,其中l.avisoPagamento.id=:idAviso order by l.dataAcao”);
最终查询queryLog=manager.createQuery(sqlLog.toString());
//Sql Aviso
最终StringBuilder sql=新StringBuilder();
追加(“选择a.id”)
.append(“a.numerioavisopagamento,”)
.append(“a.industria_id,”)
.append(“a.varejo_id”)
.append(“a.dataAvisoPagamento,”)
.append(“a.statusAvisoPagamento,”)
.append(“a.dataUploadArquivo,”)
.append(“a.dataimportacoarquivo,”)
.append(“a.dataconciliacaoviso”)
.append(“count(c.avisoPagamento_id)作为qtdeNotas,”)
.附加(“r.valorTotalBruto”)
.附加(“来自AvisoPagamento a”)
.append(“r.avisoPagamento_id=a.id上的左连接ResumoAvisoPagamento r”)
.append(“l.codigoavisopagamento=a.numerioavisopagamento上的左连接LoteAvisoPagamento l”)
.append(“c.avisoPagamento_id=l.id上的左连接Cobranca c”);
布尔值,其中=false;
//帕苏工业
如果(industria!=null){
append(“其中a.industria_id=:idIndustria”);
其中=真;
}
//帕索瓦雷霍
if(varejo!=null){
如果(!在哪里){
append(“其中a.varejo_id=:idVarejo”);
其中=真;
}否则{
append(“and a.varejo_id=:idVarejo”);
}
}
//我是阿维索先生
如果(numeroAviso!=null){
如果(!在哪里){
append(“其中a.numeravisopagamento=:numeravisopagamento”);
其中=真;
}否则{
append(“and a.numerioavisopagamento=:numerioavisopagamento”);
}
}
//作为数据的通行证
如果(数据)
//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;