Consulta realizando join entre classes com JPA e Hibernate [RESOLVIDO]

13 respostas
D

boa tarde.

estou tentando fazer a consulta abaixo utilizando JPA e Hibernate
select new br.com.entrepostosilk.dto.RelatorioFechamentoDTO(tc, sum(p.valor))
from TipoConta tc
	inner join Titulo t on t.tipoConta = tc
	inner join Parcela p on p.titulo = t
group by tc.id
mas está me retornando essas mensagens de erro
11:04:46,279 ERROR PARSER:33 - line 1:157: unexpected token: on
11:04:46,281 DEBUG ErrorCounter:28 - line 1:157: unexpected token: on
line 1:157: unexpected token: on
e
11:04:46,285 ERROR PARSER:33 - line 1:206: unexpected token: on
11:04:46,285 DEBUG ErrorCounter:28 - line 1:206: unexpected token: on
line 1:206: unexpected token: on
Já tentei de várias outras formas, entre elas
select new br.com.entrepostosilk.dto.RelatorioFechamentoDTO(tc, sum(p.valor))
from TipoConta tc
	inner join Titulo t on t.tipoConta_id = tc.id
	inner join Parcela p on p.titulo_id = t.id
group by tc.id

mas não consigo fazer funcionar de forma alguma.

minhas classes

Titulo
@Entity
@NamedQueries( { 
	//@NamedQuery(name = "titulosPorVencimento", query = "SELECT t FROM Titulo t WHERE t.dataVencimento = :dataVencimento"), 
	@NamedQuery(name = "titulosPorFornecedor", query = "SELECT t FROM Titulo t WHERE t.fornecedor = :fornecedor"), 
	@NamedQuery(name = "titulosPorTipoConta", query = "SELECT t FROM Titulo t WHERE t.tipoConta = :tipoConta"), 
	@NamedQuery(name = "titulosPorTipoDocumento", query = "SELECT t FROM Titulo t WHERE t.tipoDocumento = :tipoDocumento")
})
public class Titulo implements Serializable {

	private static final long serialVersionUID = -605302858942248346L;

	@Id
	@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="GEN_TITULO")
	@SequenceGenerator(name="GEN_TITULO", sequenceName = "GEN_ID_TITULO")
	private Long id;

	@Column(nullable = true)
	@Temporal(TemporalType.DATE)
	private Date dataEmissao;

	@Column(nullable = true, length = 255)
	private String historico;

	@Column(nullable = true, length = 20)
	private String numero;

	@Column(nullable = true, length = 255)
	private String observacao;

	@ManyToOne
	private TipoDocumento tipoDocumento;

	@ManyToOne
	private Fornecedor fornecedor;

	@ManyToOne
	private TipoConta tipoConta;

	@Column(nullable = false, length = 10)
	@Enumerated(EnumType.STRING)
	private Empresa empresa;
	
	@OneToMany(cascade=CascadeType.ALL,mappedBy="titulo", fetch=FetchType.EAGER)
	@OrderBy("dataVencimento")
	private Set<Parcela> parcelas = new TreeSet<Parcela>(new ComparatorParcelaVencimento());

	// gets e sets

}
Parcela
@Entity
@NamedQueries( { 
	@NamedQuery(name = "parcelasPorTitulo", query = "SELECT p FROM Parcela p WHERE p.titulo = :titulo")
})
public class Parcela {

	@Id
	@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="GEN_PARCELA")
	@SequenceGenerator(name="GEN_PARCELA", sequenceName = "GEN_ID_PARCELA")
	private Long id;
	
	@ManyToOne
	private Titulo titulo;
	
	@Column(nullable = false)
	@Temporal(TemporalType.DATE)
	private Date dataVencimento;

	@Column(nullable = true, precision = 15, scale = 2)
	private double valor;

	@Column(nullable = true)
	@Temporal(TemporalType.DATE)
	private Date dataPagamento;
	
	@Column(nullable = true, length = 10)
	private String parcela;

	@Column(nullable = false, length = 25)
	@Enumerated(EnumType.STRING)
	private StatusTitulo statusTitulo;

	// gets e sets
	
}
TipoConta
@Entity
public class TipoConta implements Serializable {

	private static final long serialVersionUID = 1759443150859482624L;

	@Id
	@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="GEN_TIPOCONTA")
	@SequenceGenerator(name="GEN_TIPOCONTA", sequenceName = "GEN_ID_TIPOCONTA")
	private Long id;

	@Column(length = 2, unique = true, nullable = false)
	private String codigo;

	@Column(length = 50, unique = true, nullable = false)
	private String descricao;

	// gets e sets

}
RelatorioFechamentoDTO
public class RelatorioFechamentoDTO {

	private TipoConta tipoConta;
	private double valorPago;
	
	public RelatorioFechamentoDTO(TipoConta tipoConta, double valorPago) {
		this.tipoConta = tipoConta;
		this.valorPago = valorPago;
	}
	
	// gets e sets

}

Obrigado à todos pela atenção.

13 Respostas

D

continuando o assunto do post anterior, eu fiz algumas alterações no meu código, pois percebi que estava tentando fazer uma query bem ao estilo delphi... rs

estudando melhor documentações sobre JPA, percebi que existem formas mais simples de se fazer isso, e então acabei ficando com o código abaixo.

public void filtroDadosRelatorio() {
		daoFactory.beginTransaction();
		
		Query query = daoFactory
							.getEntityManager()
							.createQuery(
									"select new br.com.entrepostosilk.dto.RelatorioFechamentoDTO(tc.codigo, tc.descricao, sum(p.valor)) " +
									"from Parcela p " +
									"	join p.titulo t " +
									"	join t.tipoConta tc " +
									"where p.dataPagamento >= :inicioPeriodo and p.dataPagamento <= :fimPeriodo)) " +
									"group by tc.codigo, tc.descricao " +
									"order by tc.codigo asc");
		
		query
			.setParameter("inicioPeriodo", DateUtil.stringToDate(inicioPeriodo))
			.setParameter("fimPeriodo", DateUtil.stringToDate(fimPeriodo));
		
		relatorio = query.getResultList();
		
		daoFactory.commit();
	}
observem que eu adicionei o
group by tc.codigo, tc.descricao
ao select, porém o hibernate não acrescenta o bendito no select enviado para o banco. o select que ele gera é esse:
select tipoconta2_.codigo as col_0_0_, tipoconta2_.descricao as col_1_0_, sum(parcela0_.valor) as col_2_0_ from Parcela parcela0_ inner join Titulo titulo1_ on parcela0_.titulo_id=titulo1_.id inner join TipoConta tipoconta2_ on titulo1_.tipoConta_id=tipoconta2_.id where parcela0_.dataPagamento>=? and parcela0_.dataPagamento<=?
se eu executo o select exatamente como está, o Firebird (que é o banco que estou utilizando) dispara a exceção
Invalid expression in the select list (not contained in either an aggregate function or the GROUP BY clause)
quando eu adiciono manualmente o
group by tipoconta2_.codigo, tipoconta2_.descricao
ele funciona normalmente.

alguém tem idéia de como eu faço para "obrigar" o hibernate a incluir essa cláusula automaticamente?

obrigado.

D

up

D

up

D

Consegui resolver meu problema.

Solução aqui: http://douglascrp.blogspot.com/2008/03/join-entre-classes-com-group-by.html

Abraços

D

up

Herrera

ola,
eu estou com um problema parecido, Sao duas tabelas, uma de Recebimento e outra de Desembolso e preciso fazer um join pela data para saber o valor resultando por dia do tipo :

data vlaor recebido valor Desembolso
01/08 1000,00 2000

como faço usando hsql ? eu tenho a query pronta funcionando em forma nativa. mas queria transforma-la para hsql , é possivel ?

SELECT nvl2(d.data, d.data, r.data) data, sum(d.valor) desembolso, sum(r.valor_recebido) recebimento FROM interno.desembolso d FULL OUTER JOIN interno.recebimento r ON d.DATA = r.DATA group by nvl2(d.data, d.data, r.data) order by nvl2(d.data, d.data, r.data)

Valeu

Herrera

D

os “modelos” de consulta que coloquei aí e a solução do problema no meu blog não ajudaram?

o que você já tentou fazer?
posta o código.

qq coisa, dá um grito

abraços

Herrera

Ola Douglas,

nao ajudou muito. São duas tabelas distintas que nao tem relacao alguma entre elas e o que preciso fazer é o join pela data. como fazer isso ?

Herrera

D

Herrera, tudo bem?

E aí? Você conseguiu resolver o seu problema?

Não consegui te responder antes. Só arrumei uma folga agora.

T+

R

ressuscitando o tópico
tenho a seguinte consulta em SQL &#65279;select doc.titulo as Título, p.nome as Autor, a.descricao as Área, c.curso as Curso from documento doc join curso c on c.codigo = doc.curso join area a on a.codigo = doc.area join documento_autor da on doc.codigo = da.cod_doc join pessoa p on p.codigo = da.cod_autor WHERE doc.titulo LIKE '% parâmetro que vou colocar%';

em JPA seria como?, usando a @NamedQuery
acho que não é preciso eu colocar os on c.codigo= doc.curso

D

Não tenho um ambiente para validar a resposta, mas creio que o exemplo que postei no meu blog deve responder a pergunta.

select tc.id,
      sum(p.valor),
      t.empresa
from Parcela p
 join p.titulo t
 join t.tipoConta tc
where p.dataPagamento >= :inicioPeriodo and
	p.dataPagamento <= :fimPeriodo and
	t.empresa = :empresa 
group by tc.id, 
	tc.codigo, ]
	t.empresa 
order by t.empresa, tc.codigo asc

Note que não utilizei os on c.codigo= doc.curso

Tenta fazer algo do tipo e diz depois se funcionou.
Se não resolver, comenta aqui denovo que tento te ajudar com seu problema.

Abraço

roregk:
ressuscitando o tópico
tenho a seguinte consulta em SQL &#65279;select doc.titulo as Título, p.nome as Autor, a.descricao as Área, c.curso as Curso from documento doc join curso c on c.codigo = doc.curso join area a on a.codigo = doc.area join documento_autor da on doc.codigo = da.cod_doc join pessoa p on p.codigo = da.cod_autor WHERE doc.titulo LIKE '% parâmetro que vou colocar%';

em JPA seria como?, usando a @NamedQuery
acho que não é preciso eu colocar os on c.codigo= doc.curso

R

ok entendi o esquema dos joins
só mais uma pergunta,

SELECT 
  p.nome AS "Autor", 
  d.titulo AS "Titulo"
FROM 
  documento d
join
  documento_autor da
on da.cod_doc=d.codigo
join
  pessoa p
on da.cod_autor=p.codigo
where d.titulo like'%a%';,

esse SQl vai trazer isso:

…Autor…|…Titulo…|
“Fernando Arthur Weber”…|“AgroJava”…|
“Gustavo Wentz”…|"Milk JAVA:…|
“Edimar Manica”…|"AgroJava:…|
“Edimar Manica”…|"Milk JAVA…|

note que Edimar participou dos dois trabalhos,
como eu faria para ver apenas 3 autores e 2 documentos, acho que tenho que usar List<E>, mas como?

D

Se você está trabalhando no nível de registros, você vai receber o retorno que você apresentou mesmo.
O resultado que você apresentou está certo.

Não entendi o seu problema.

Você tem dúvidas no código java?

roregk:
ok entendi o esquema dos joins
só mais uma pergunta,

SELECT 
  p.nome AS "Autor", 
  d.titulo AS "Titulo"
FROM 
  documento d
join
  documento_autor da
on da.cod_doc=d.codigo
join
  pessoa p
on da.cod_autor=p.codigo
where d.titulo like'%a%';,

esse SQl vai trazer isso:

…Autor…|…Titulo…|
“Fernando Arthur Weber”…|“AgroJava”…|
“Gustavo Wentz”…|"Milk JAVA:…|
“Edimar Manica”…|"AgroJava:…|
“Edimar Manica”…|"Milk JAVA…|

note que Edimar participou dos dois trabalhos,
como eu faria para ver apenas 3 autores e 2 documentos, acho que tenho que usar List<E>, mas como?

Criado 20 de março de 2008
Ultima resposta 17 de abr. de 2012
Respostas 13
Participantes 3