Hibernate Criteria + OneToMany

Olá,

Tenho esse relacionamento:

Departamento.java

public class Departamento
{
	private Long id;
	private String nome;
	private Date dataCriacao;
	private Date dataAlteracao;
	
	private List<Recurso> cargos;

	@OneToMany(targetEntity=Cargo.class, mappedBy="departamento", fetch=FetchType.EAGER)
	@JoinColumn(name="fk_depId")
	public List<Recurso> getCargos()
	{
		return cargos;
	}

	public void setCargos(List<Recurso> cargos)
	{
		this.cargos = cargos;
	}
}

Cargo.java

public class Cargo implements Recurso
{
	private Long id;
	private String nome;
	private double valorHora;
	private Date dataCriacao;
	private Date dataAlteracao;
	
	private Empresa empresa;
	private Fornecedor fornecedor;
	private Departamento departamento;
	private List<Funcionario> funcionarios;

	@ManyToOne(targetEntity=Departamento.class)
	@JoinColumn(name="fk_depId")
	@ForeignKey(name="dep_id")
	public Departamento getDepartamento()
	{
		return departamento;
	}
	public void setDepartamento(Departamento departamento)
	{
		this.departamento = departamento;
	}
}

Fornecedor.java

public class Fornecedor
{
	private Long id;
	private String apelido;
	private String razaoSocial;
	private Date dataCriacao;
	private Date dataAlteracao;
	
	private List<Cargo> cargos;

	@OneToMany(mappedBy="fornecedor", targetEntity=Cargo.class, fetch=FetchType.EAGER)
	public List<Cargo> getCargos()
	{
		return cargos;
	}
	public void setCargos(List<Cargo> cargos)
	{
		this.cargos = cargos;
	}
}

*obs.: coloquei apenas os relacionamentos necessários para a pergunta

Departamento 1 : N Cargo
Cargo 1 : 1 Fornecedor
Cargo 1 : 1 Empresa

Ou seja, o Cargo pertence a Fornecedor OU a Empresa.

Estou tentando atualmente esta query para fazer a consulta de todos os departamentos onde o FORNECEDOR do cargo seja NULL:

@SuppressWarnings("unchecked")
public List<Departamento> listarPorCargoInterno()
{
	Criteria crit = getSession().createCriteria(getPersistentClass());
	crit.add(Restrictions.isNull("cargos")).setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
	return (List<Departamento>) crit.list();
}

Já tentei outras maneiras tb, mas não consigo fazer esse filtro. Como devo fazer?

abs

Galera, alguém consegue dar uma luz?

Em SQL seria algo como:

abs.

Já tentou criando um alias para “cargos” para ve se resolve.

Já sim. Mas não da certo, pois eu tenho uma lista de cargos, e não um só para criar um alias. Não sei como fazer nessa situação =[

Ninguém nunca teve uma situacao parecida? A meu ver, é uma relação e um tipo de filtro bem comum.

Tenho uma lista da EntidadeA na EntidadeB e gostaria de filtrar apenas as EntidadeA que tivessem o status = 1, por exemplo. É exatamente o que estou passando, mas minha inexperiência com Hibernate me faz travar nuns problemas bem básicões =\

rapaz se não esta conseguindo, utilize HQL ou o metodo SQL Restrictions do DetacheCriteria e passe o SQL da consulta se esta tendo tanta dificuldade com criteria, eu particularmente já utilizei o alias para coleções e funcionou, mas nunca no caso de testar de uma entidade toda é null, mas para esse caso aqui:

um alias normalmente sempre resolve, mande exibir o SQL na consulta se esta dando erro poste a exceção aqui para poder facilitar e até mesmo os códigos, caso sejam diferentes dos que esta no inicio do post.

Esta usando o hibernate com annotations?

Sim, estou usando annotations. Segue meu codigo atual:

public List<Departamento> listarPorCargoInterno()
{
	Criteria crit = getSession().createCriteria(getPersistentClass());
	crit.createAlias("cargos", "c");
	crit.add(Restrictions.isNull("c.fornecedor")).setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
	return (List<Departamento>) crit.list();
}

Resultado:

TECNOLOGIA
Programador PHP >> 10 >> sigo.model.Empresa@1ee2c2c
Programador ActionScript >> 15 >> sigo.model.Empresa@1ee2c2c
Programador PHP >> 28 >> null
Programador PHP >> 29 >> null
Programador PHP >> 30 >> null
Programador ActionScript >> 31 >> null
Programador ActionScript >> 32 >> null
Programador ActionScript >> 33 >> null
Programador .NET >> 34 >> null
Programador .NET >> 35 >> null
Programador .NET >> 36 >> null
PLANEJAMENTO
Planejador >> 11 >> sigo.model.Empresa@1ee2c2c
PROJETOS
Gerente de Projetos >> 13 >> sigo.model.Empresa@1ee2c2c
Gerente de Projetos >> 37 >> null
Gerente de Projetos >> 38 >> null
Gerente de Projetos >> 39 >> null
ATENDIMENTO
Atendimento >> 12 >> sigo.model.Empresa@1ee2c2c

Ele deveria ter excluído da consulta todos esses nulls

SQL gerado

00:50:07,414 DEBUG SQL:111 - select cargos0_.fk_depId as fk6_3_, cargos0_.cargo_id as cargo1_3_, cargos0_.cargo_id as cargo1_8_2_, cargos0_.cargo_dataAlteracao as cargo2_8_2_, cargos0_.cargo_dataCriacao as cargo3_8_2_, cargos0_.fk_depId as fk6_8_2_, cargos0_.fk_empId as fk7_8_2_, cargos0_.fk_fornecedorId as fk8_8_2_, cargos0_.cargo_nome as cargo4_8_2_, cargos0_.cargo_valorHora as cargo5_8_2_, empresa1_.emp_id as emp1_9_0_, empresa1_.emp_apelido as emp2_9_0_, empresa1_.emp_dataAlteracao as emp3_9_0_, empresa1_.emp_dataCriacao as emp4_9_0_, empresa1_.emp_nome as emp5_9_0_, empresa1_.emp_overhead as emp6_9_0_, empresa1_.emp_profit as emp7_9_0_, fornecedor2_.for_id as for1_11_1_, fornecedor2_.for_apelido as for2_11_1_, fornecedor2_.for_dataAlteracao as for3_11_1_, fornecedor2_.for_dataCriacao as for4_11_1_, fornecedor2_.for_razaoSocial as for5_11_1_ from cargo cargos0_ left outer join empresa empresa1_ on cargos0_.fk_empId=empresa1_.emp_id left outer join fornecedor fornecedor2_ on cargos0_.fk_fornecedorId=fornecedor2_.for_id where cargos0_.fk_depId=?

Hibernate: select cargos0_.fk_depId as fk6_3_, cargos0_.cargo_id as cargo1_3_, cargos0_.cargo_id as cargo1_8_2_, cargos0_.cargo_dataAlteracao as cargo2_8_2_, cargos0_.cargo_dataCriacao as cargo3_8_2_, cargos0_.fk_depId as fk6_8_2_, cargos0_.fk_empId as fk7_8_2_, cargos0_.fk_fornecedorId as fk8_8_2_, cargos0_.cargo_nome as cargo4_8_2_, cargos0_.cargo_valorHora as cargo5_8_2_, empresa1_.emp_id as emp1_9_0_, empresa1_.emp_apelido as emp2_9_0_, empresa1_.emp_dataAlteracao as emp3_9_0_, empresa1_.emp_dataCriacao as emp4_9_0_, empresa1_.emp_nome as emp5_9_0_, empresa1_.emp_overhead as emp6_9_0_, empresa1_.emp_profit as emp7_9_0_, fornecedor2_.for_id as for1_11_1_, fornecedor2_.for_apelido as for2_11_1_, fornecedor2_.for_dataAlteracao as for3_11_1_, fornecedor2_.for_dataCriacao as for4_11_1_, fornecedor2_.for_razaoSocial as for5_11_1_ from cargo cargos0_ left outer join empresa empresa1_ on cargos0_.fk_empId=empresa1_.emp_id left outer join fornecedor fornecedor2_ on cargos0_.fk_fornecedorId=fornecedor2_.for_id where cargos0_.fk_depId=?

Obrigado.

abs,
André Vendramini

Rapaz pelo que entendi da consulta tu quer todos em que fornecedor for null correto?

Esse null dessa linha significa o que? a Empresa? estou achando é que esta faltando coisas nessa sua criteria.

É a empresa sim… tanto é que alguns retornam: sigo.model.Empresa@1ee2c2c que são os cargos que pertencem a uma empresa. Segue o trace agora exibindo os fornecedores do Cargo:

CRIAÇAO
Redator >> 8 >> sigo.model.Empresa@1963b3e >> null
Redator >> 9 >> sigo.model.Empresa@2db19d >> null
Diretor de Arte >> 14 >> sigo.model.Empresa@2db19d >> null
Redator >> 16 >> null >> sigo.model.Fornecedor@c3014
Redator >> 17 >> null >> sigo.model.Fornecedor@16dfa45
Redator >> 18 >> null >> sigo.model.Fornecedor@15718f2
Diretor de Arte >> 19 >> null >> sigo.model.Fornecedor@15718f2
Diretor de Arte >> 20 >> null >> sigo.model.Fornecedor@16dfa45
Diretor de Arte >> 21 >> null >> sigo.model.Fornecedor@c3014
Assistente de Arte >> 22 >> null >> sigo.model.Fornecedor@c3014
Assistente de Arte >> 23 >> null >> sigo.model.Fornecedor@16dfa45
Assistente de Arte >> 24 >> null >> sigo.model.Fornecedor@15718f2
Diretor de Criação >> 25 >> null >> sigo.model.Fornecedor@15718f2
Diretor de Criação >> 26 >> null >> sigo.model.Fornecedor@16dfa45
Diretor de Criação >> 27 >> null >> sigo.model.Fornecedor@c3014
TECNOLOGIA
Programador PHP >> 10 >> sigo.model.Empresa@1963b3e >> null
Programador ActionScript >> 15 >> sigo.model.Empresa@1963b3e >> null
Programador PHP >> 28 >> null >> sigo.model.Fornecedor@c3014
Programador PHP >> 29 >> null >> sigo.model.Fornecedor@16dfa45
Programador PHP >> 30 >> null >> sigo.model.Fornecedor@15718f2
Programador ActionScript >> 31 >> null >> sigo.model.Fornecedor@15718f2
Programador ActionScript >> 32 >> null >> sigo.model.Fornecedor@16dfa45
Programador ActionScript >> 33 >> null >> sigo.model.Fornecedor@c3014
Programador .NET >> 34 >> null >> sigo.model.Fornecedor@c3014
Programador .NET >> 35 >> null >> sigo.model.Fornecedor@16dfa45
Programador .NET >> 36 >> null >> sigo.model.Fornecedor@15718f2
PLANEJAMENTO
Planejador >> 11 >> sigo.model.Empresa@1963b3e >> null
PROJETOS
Gerente de Projetos >> 13 >> sigo.model.Empresa@1963b3e >> null
Gerente de Projetos >> 37 >> null >> sigo.model.Fornecedor@15718f2
Gerente de Projetos >> 38 >> null >> sigo.model.Fornecedor@16dfa45
Gerente de Projetos >> 39 >> null >> sigo.model.Fornecedor@c3014
ATENDIMENTO
Atendimento >> 12 >> sigo.model.Empresa@1963b3e >> null

Se existe Empresa, Fornecedor é null. Se existe Fornecedor, Empresa é null.

No meu Criteria, estou criando um alias de uma lista de Cargo e digo que Restrictions.isNull(“c.fornecedor”) (onde “c” é o alias para a lista de Cargo)
Está certo isso? Bom, não, pois não funciona como deveria, rsrs…

Obrigado,

André Vendramini

Alguém consegue dar uma ajuda nesse problema? Nesse meu último post está bem exemplificado o que está acontecendo e o que estou tentando fazer… é simples, não? Procurei posts relacionandos aqui e em outros fóruns mas nada… inclusive tem um cara aqui com a mesma dúvida que eu mas sem respostas: https://forum.hibernate.org/viewtopic.php?f=1&t=1002167&view=previous

Olá, André, acredito que a essa altura você já deve ter encontrado outra saída, mas passei pelo mesmo problema e encontrei a seguinte solução:

Criteria crit = getSession().createCriteria(getPersistentClass());
crit.createCriteria("cargos").add(Restrictions.isNull("fornecedor"));
return (List<Departamento>) crit.list();

Fica ae para o caso de alguém passar pelo problema.

Abç!

Victor Bonafé