Pessoal,
Primeiramente, seguem abaixo classe e tabela:
CLASSE:
@Entity
@Table(name="fin_LancamentosDespesas")
public class LancamentoDespesa extends MappedEntity{
private static final long serialVersionUID = 2114159600713444333L;
private Integer numeroLancamento;
private Date dataCompetencia;
private Date dataEmissao;
private String observacao;
private String numeroDocumento;
private Date dataOperacao;
private UsuarioSIG responsavelOperacao;
private Boolean flagCaixa;
private Double valorBruto;
private Double valorLiquido;
private UsuarioSIG responsavelConferencia;
private Fornecedor fornecedor;
private TipoDocumento tipoDocumento;
private Date dataConferencia;
private Empresa empresa;
private TipoOrigem tipoOrigem;
private Date dataCancelamento;
private List<ParcelaLancamentoDespesa> listaParcela;
private List<RateioLancamento> listaRateio;
private List<RetencaoLancamentoDespesa> listaRetencao;
@Id
@Override
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "NUMG_LancamentoDespesa")
public Long getId() {
return super.getId();
}
@Column(name="NUMR_LancamentoDespesa")
public Integer getNumeroLancamento() {
return numeroLancamento;
}
public void setNumeroLancamento(Integer numeroLancamento) {
this.numeroLancamento = numeroLancamento;
}
@Column(name="DATA_Cancelamento")
@Temporal(TemporalType.TIMESTAMP)
public Date getDataCancelamento() {
return dataCancelamento;
}
public void setDataCancelamento(Date dataCancelamento) {
this.dataCancelamento = dataCancelamento;
}
@Column(name = "DATA_Competencia")
@NotNull(message = "A data competência do lançamento deve ser preenchida.")
public Date getDataCompetencia() {
return dataCompetencia;
}
public void setDataCompetencia(Date dataCompetencia) {
this.dataCompetencia = dataCompetencia;
}
@Column(name = "DATA_Emissao")
@NotNull(message = "A data emissão do lançamento deve ser preenchida.")
@Temporal(TemporalType.DATE)
public Date getDataEmissao() {
return dataEmissao;
}
public void setDataEmissao(Date dataEmissao) {
this.dataEmissao = dataEmissao;
}
@Column(name = "DESC_Observacao")
public String getObservacao() {
return observacao;
}
public void setObservacao(String observacao) {
this.observacao = observacao;
}
@Column(name = "CODG_Documento")
@NotNull(message = "O numero documeto do lançamento deve ser preenchido.")
public String getNumeroDocumento() {
return numeroDocumento;
}
public void setNumeroDocumento(String numeroDocumento) {
this.numeroDocumento = numeroDocumento;
}
@Column(name = "DATA_Operacao")
@NotNull(message = "A data de operação do lançamento deve ser preenchida.")
public Date getDataOperacao() {
return dataOperacao;
}
public void setDataOperacao(Date dataOperacao) {
this.dataOperacao = dataOperacao;
}
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "NUMG_UsuarioOperacao")
@NotNull(message = "O responsável operação do lançamento deve ser preenchido.")
public UsuarioSIG getResponsavelOperacao() {
return responsavelOperacao;
}
public void setResponsavelOperacao(UsuarioSIG responsavelOperacao) {
this.responsavelOperacao = responsavelOperacao;
}
@Column(name = "FLAG_Caixa")
@NotNull(message = "O flag caixa do lançamento deve ser preenchido.")
public Boolean getFlagCaixa() {
return flagCaixa;
}
public void setFlagCaixa(Boolean flagCaixa) {
this.flagCaixa = flagCaixa;
}
@Column(name = "VALR_Bruto")
@NotNull(message = "O valor bruto do lançamento deve ser preenchido.")
public Double getValorBruto() {
return valorBruto;
}
public void setValorBruto(Double valorBruto) {
this.valorBruto = valorBruto;
}
@Column(name = "VALR_Liquido")
@NotNull(message = "O valor líquido do lançamento deve ser preenchido.")
public Double getValorLiquido() {
return valorLiquido;
}
public void setValorLiquido(Double valorLiquido) {
this.valorLiquido = valorLiquido;
}
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "NUMG_UsuarioConferencia")
public UsuarioSIG getResponsavelConferencia() {
return responsavelConferencia;
}
public void setResponsavelConferencia(UsuarioSIG responsavelConferencia) {
this.responsavelConferencia = responsavelConferencia;
}
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "NUMG_Fornecedor")
@NotNull(message = "O fornecedor do lançamento deve ser preenchido.")
public Fornecedor getFornecedor() {
return fornecedor;
}
public void setFornecedor(Fornecedor fornecedor) {
this.fornecedor = fornecedor;
}
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "NUMG_DocumentoTipo")
@NotNull(message = "O tipo documento do lançamento deve ser preenchido.")
public TipoDocumento getTipoDocumento() {
return tipoDocumento;
}
public void setTipoDocumento(TipoDocumento tipoDocumento) {
this.tipoDocumento = tipoDocumento;
}
@Column(name = "DATA_Conferencia")
@Temporal(TemporalType.TIMESTAMP)
public Date getDataConferencia() {
return dataConferencia;
}
public void setDataConferencia(Date dataConferencia) {
this.dataConferencia = dataConferencia;
}
@OneToMany(mappedBy = "lancamentoDespesa", fetch = FetchType.LAZY, cascade = { CascadeType.PERSIST, CascadeType.MERGE })
@Cascade( { org.hibernate.annotations.CascadeType.SAVE_UPDATE, org.hibernate.annotations.CascadeType.DELETE_ORPHAN })
public List<ParcelaLancamentoDespesa> getListaParcela() {
if (listaParcela == null){
listaParcela = new ArrayList<ParcelaLancamentoDespesa>();
}
return listaParcela;
}
public void setListaParcela(List<ParcelaLancamentoDespesa> listaParcela) {
this.listaParcela = listaParcela;
}
@OneToMany(mappedBy = "lancamentoDespesa", fetch = FetchType.LAZY, cascade = { CascadeType.PERSIST, CascadeType.MERGE })
@Cascade( { org.hibernate.annotations.CascadeType.SAVE_UPDATE, org.hibernate.annotations.CascadeType.DELETE_ORPHAN })
public List<RateioLancamento> getListaRateio() {
if (listaRateio == null){
listaRateio = new ArrayList<RateioLancamento>();
}
return listaRateio;
}
public void setListaRateio(List<RateioLancamento> listaRateio) {
this.listaRateio = listaRateio;
}
@OneToMany(mappedBy = "lancamentoDespesa", fetch = FetchType.LAZY, cascade = { CascadeType.PERSIST, CascadeType.MERGE })
@Cascade( { org.hibernate.annotations.CascadeType.SAVE_UPDATE, org.hibernate.annotations.CascadeType.DELETE_ORPHAN })
public List<RetencaoLancamentoDespesa> getListaRetencao() {
if (listaRetencao == null){
listaRetencao = new ArrayList<RetencaoLancamentoDespesa>();
}
return listaRetencao;
}
public void setListaRetencao(List<RetencaoLancamentoDespesa> listaRetencao) {
this.listaRetencao = listaRetencao;
}
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "NUMG_Empresa")
@NotNull(message = "A empresa do lançamento deve ser preenchida.")
public Empresa getEmpresa() {
return empresa;
}
public void setEmpresa(Empresa empresa) {
this.empresa = empresa;
}
@Column(name = "TIPO_Origem")
@Type(type = "org.hibernate.usertype.TipoOrigemUserType")
@NotNull(message = "A origem do Lancamento Deve se informada.")
public TipoOrigem getTipoOrigem() {
return tipoOrigem;
}
public void setTipoOrigem(TipoOrigem tipoOrigem) {
this.tipoOrigem = tipoOrigem;
}
}
TABELA
Column_name Type
NUMG_LancamentoDespesa int
NUMR_Versao smallint
DATA_Competencia smalldatetime
DATA_Emissao datetime
DESC_Observacao varchar
CODG_Documento varchar
DATA_Operacao datetime
NUMG_UsuarioOperacao int
FLAG_Caixa bit
VALR_Bruto money
VALR_Liquido money
NUMG_UsuarioConferencia int
DATA_Conferencia datetime
NUMG_Fornecedor int
NUMG_DocumentoTipo tinyint
NUMG_Empresa smallint
TIPO_Origem tinyint
NUMR_LancamentoDespesa int
DATA_Cancelamento datetime
Estou procurando exemplos de criteria utilizando subquery mas só achei exemplos onde o join é somente com uma coluna, tipo (código 1):
SELECT ld.*
FROM dbo.fin_LancamentosDespesas ld
INNER JOIN (
SELECT MAX(DATA_Operacao) AS DATA_Operacao
FROM dbo.fin_LancamentosDespesas
WHERE NUMG_Empresa = 70
AND CODG_Documento = '210109-002'
AND DATA_Emissao = '2009-01-21 00:00:00.000'
AND NUMG_Fornecedor = 58
AND NUMG_DocumentoTipo = 5
AND DATA_Cancelamento = '1900-01-01 00:00:00.000'
GROUP BY NUMR_LancamentoDespesa) ldt
ON ld.DATA_Operacao = ldt.DATA_Operacao
O que estou precisando é de um join entre dois campos (código 2):
SELECT ld.*
FROM dbo.fin_LancamentosDespesas ld
INNER JOIN (
SELECT MAX(DATA_Operacao) AS DATA_Operacao, NUMR_LancamentoDespesa
FROM dbo.fin_LancamentosDespesas
WHERE NUMG_Empresa = 70
AND CODG_Documento = '210109-002'
AND DATA_Emissao = '2009-01-21 00:00:00.000'
AND NUMG_Fornecedor = 58
AND NUMG_DocumentoTipo = 5
AND DATA_Cancelamento = '1900-01-01 00:00:00.000'
GROUP BY NUMR_LancamentoDespesa) ldt
ON ld.NUMR_LancamentoDespesa = ldt.NUMR_LancamentoDespesa
AND ld.DATA_Operacao = ldt.DATA_Operacao
O máximo que consegui chegar com criteria foi (código 3):
select
this_.*
from
dbo.fin_LancamentosDespesas this_
where
exists (
select
max(this0__.DATA_Operacao) as y0_,
this0__.NUMR_LancamentoDespesa as y1_
from
dbo.fin_LancamentosDespesas this0__
where
this_.CODG_Documento='210109-002'
and this_.DATA_Emissao='2009-01-21 00:00:00.000'
and this_.NUMG_Fornecedor=58
and this_.NUMG_Empresa=70
and this_.NUMG_DocumentoTipo = 5
and this_.DATA_Cancelamento='1900-01-01 00:00:00.000'
and this0__.DATA_Operacao=this_.DATA_Operacao
and this0__.NUMR_LancamentoDespesa=this_.NUMR_LancamentoDespesa
group by
this0__.NUMR_LancamentoDespesa
)
E o código da criteria utilizado foi (código 4):
DetachedCriteria dc = DetachedCriteria.forClass(LancamentoDespesa.class,"ld");
dc.setProjection(
Projections.projectionList()
.add(Projections.max("ld.dataOperacao"))
.add(Projections.groupProperty("ld.numeroLancamento"))
);
dc.add(Restrictions.eq("ld.numeroDocumento", numeroDocumento));
dc.add(Restrictions.eq("ld.dataEmissao", dataEmissao));
dc.add(Restrictions.eq("ld.fornecedor", fornecedor));
dc.add(Restrictions.eq("ld.empresa", empresa));
dc.add(TSQLFunctions.is1900("ld.dataCancelamento"));
dc.add(Property.forName("ld.dataOperacao").eqProperty("ld1.dataOperacao"));
dc.add(Property.forName("ld.numeroDocumento").eqProperty("ld1.numeroDocumento"));
Criteria c = session.createCriteria(LancamentoDespesa.class,"ld1")
.add(Subqueries.exists(dc));
Gostaria de saber se há uma forma de conseguir gerar o SQL do código 2.
Obrigado.