[RESOLVIDO] Listar animais que não estão na tabela mortalidade

Olá
estou fazendo um sistema para controle leiteiro
e uso o hibernate
no banco de dados tenho as tabelas produtor, animal e mortalidade
quando um animal morre, eu não quero exclui-lo do banco, pois quero manter um registro de todos os animais
então eu coloco ele na tabela mortalidade.
porém quando eu buscar os animais, preciso trazer somente os 'vivos’
então eu precisaria de uma forma de buscar animais que não estão ligados a tabela mortalidade
e eu não sei como fazer isso no hibernate.

aqui está minha consulta que eu fiz
mas ela só está pesquisando os animais do produtor selecionado
está vindo as vivas e as mortas

public List<Animal> listar(Produtor p) {
        Session session = null;
        try {
            session = factory.openSession();
            Criteria consulta = session.createCriteria(Animal.class);
            consulta.add(Expression.eq("produtor", p));
            consulta.add();         <------------------------------------------- adicionar mais uma expressão para mortalidade
            List<Animal> resultado = consulta.list();
            session.flush();
            return resultado;

minha classe animal:

@Entity
@SequenceGenerator(name="seq_animal", sequenceName="animal_idanimal_seq", allocationSize = 1, initialValue = 1)
@Table(name="animal"
    ,schema="public"
)
public class Animal  implements Comparable<Animal>, java.io.Serializable {
    @Transient
    private PropertyChangeSupport changeSupport = new PropertyChangeSupport(this);


     private int idanimal;
     private Raca raca;
     private Produtor produtor;
     private String nome;
     private Integer numbrinco;
     private Date datanasc;
     private Integer numregistro;
     private Character sexo;
     private String nomepai;
     private String nomemae;
     private Set mortalidades = new HashSet(0);
     private Set lactacaos = new HashSet(0);
     private Set inseminacaos = new HashSet(0);
     private Set medicamentos = new HashSet(0);

    public Animal() {
    }

	
    public Animal(int idanimal, Raca raca, Produtor produtor) {
        this.idanimal = idanimal;
        this.raca = raca;
        this.produtor = produtor;
    }

Classe mortalidade:

@Entity
@SequenceGenerator(name="seq_mortalidade", sequenceName="mortalidade_idmortalidade_seq", allocationSize = 1, initialValue = 1)
@Table(name="mortalidade"
    ,schema="public"
)
public class Mortalidade  implements java.io.Serializable {


     private int idmortalidade;
     private Motivomortalidade motivomortalidade;
     private Animal animal;
     private Date datamort;

    public Mortalidade() {
    }

bom pensando rapidamente eu faria o seguinte: criava mais um campo na tabela animal…tipow: boolean vivo e conforme fosse inserindo novos animais setava esse campo como true…qdo morresse e fosse ir pra tabela mortalidade eu setava esse campo como false…dai qdo eu fosse filtrar so chamaria os animais com esse campo true, pronto resolvido o problema…logico q isso é uma forma chula de fazer existem outras mais usuais, mas…

No SQL isso é muito fácil de fazer, só não sei como faz no hibernate xD

com hql vc pode fazer assim:

ffrom eg.Cat as cat
where not exists (
from eg.Cat as mate where mate.mate = cat
)

ou

from eg.DomesticCat as cat
where cat.name not in (
select name.nickName from eg.Name as name
)

com criteria acho q seria +ou- assim:

DetachedCriteria subquery = DetachedCriteria.forClass(UserGame.class, “ug”)
.add(Restrictions.eq(“ug.user.id”, 1))
.add(Restrictions.eqProperty(“ug.game.id”,“u.id”));
DetachedCriteria criteria = DetachedCriteria.forClass(Game.class, “g”)
.add(Subqueries.notExists(subquery));

teria q usar subquery

ou poderia carregas os animais mortos em um List e passar como Restrictions not in para a criteria

Consegui,
fuçando mais um pouco, achei o que eu queria
não sei se é a melhor forma de fazer isso
o que eu fiz foi isso:

Rodou beleza com isso
ou tem alguma forma melhor?
tipo, que de mais desempenho ou ocupe menos memoria, algo assim…

Luxu

Tava quase fazendo isso jah…

Jacomete

isso não iria trazer somente o do usuario com id igual a 1???
e eu nao entendi como que eu iria separar os animais mortos com o seu exemplo

e qual a diferença de usar DetachedCriteria de criteria???
são usados separados ou usa os dois juntos?
pois quando uso o criteria, eu trago os dados com o metodo List() ou uniqueResult()
no DetachedCriteria nao tem esses metodos
como q é feito dai?
Muito obrigado

isso foi soh um exemplo

DetachedCriteria subquery = DetachedCriteria.forClass(UserGame.class, "ug")
.add(Restrictions.eq("ug.user.id", 1))
.add(Restrictions.eqProperty("ug.game.id","u.id"));
DetachedCriteria criteria = DetachedCriteria.forClass(Game.class, "g")
.add(Subqueries.notExists(subquery)); 

na realidade q interessa ai e a subquery usando o notExists

Para usar qualquer método da Subqueries precisamos de uma DetachedCriteria. Essa DetachedCriteria é um tipo especial de Criteria que não precisa da session do hibernate para ser criada. Dentro dela temos acesso a todos os alias e propriedades da Criteria principal, e o uso é o mesmo que faríamos para Criterias normais.

nesse link tem uns exemplos http://blog.caelum.com.br/divisions-com-hibernate-uso-avancado-da-criteria-api/

Valeu Jacomete, ja está salvo nos meus favoritos o link

precisei fazer um aki muito parecido com o seu

“Buscar todos os usuarios que não estão na tabela de acesso”

solução:

		Session session = getHibernateTemplate().getSessionFactory().openSession(); 
		
		Criteria criteria = session.createCriteria(UsuarioH.class,"usuario");			
	
		DetachedCriteria subconsulta = DetachedCriteria.forClass(AcessoH.class).setProjection(Property.forName("usuario"));  
		
		criteria.add(Property.forName("id").notIn(subconsulta));	
		
		return criteria.list();

select gerando pelo Hibernate:

select this_.id as id0_0_, this_.dataNascimento as dataNasc2_0_0_, this_.login as login0_0_, this_.nome as nome0_0_, this_.senha as senha0_0_ from UsuarioH this_ where this_.id not in (select this0__.usuario_id as y0_ from AcessoH this0__)

Ahh, agora com esse exemplo consegui faze blz

no meu caso fica assim

[code]
Criteria consulta = session.createCriteria(Animal.class);
consulta.add(Expression.eq(“produtor”, p));
DetachedCriteria subconsulta = DetachedCriteria.forClass(Mortalidade.class).setProjection(Property.forName(“animal”));
consulta.add(Property.forName(“idanimal”).notIn(subconsulta));

        List<Animal> resultado = consulta.list();
        session.flush();
        return resultado;[/code]

SQL:

select this_.idanimal as idanimal41_2_, this_.datanasc as datanasc41_2_, this_.nome as nome41_2_, this_.nomemae as nomemae41_2_, this_.nomepai as nomepai41_2_, this_.numbrinco as numbrinco41_2_, this_.numregistro as numregis7_41_2_, this_.produtor_idprodutor as produtor9_41_2_, this_.raca_idraca as raca10_41_2_, this_.sexo as sexo41_2_, produtor2_.idprodutor as idprodutor34_0_, produtor2_.localidade as localidade34_0_, produtor2_.municipio as municipio34_0_, produtor2_.nome as nome34_0_, produtor2_.propriedade as propried5_34_0_, raca3_.idraca as idraca35_1_, raca3_.descricao as descricao35_1_ from public.animal this_ inner join public.produtor produtor2_ on this_.produtor_idprodutor=produtor2_.idprodutor inner join public.raca raca3_ on this_.raca_idraca=raca3_.idraca where this_.produtor_idprodutor=? and this_.idanimal not in (select this0__.animal_idanimal as y0_ from public.mortalidade this0__)

E aqui como eu tinha feito antes:

[code]
Criteria consulta = session.createCriteria(Animal.class);
consulta.add(Expression.eq(“produtor”, p));
consulta.add(Expression.isEmpty(“mortalidades”));

        List<Animal> resultado = consulta.list();
        session.flush();
        return resultado;[/code]

SQL

Hibernate: select this_.idanimal as idanimal41_2_, this_.datanasc as datanasc41_2_, this_.nome as nome41_2_, this_.nomemae as nomemae41_2_, this_.nomepai as nomepai41_2_, this_.numbrinco as numbrinco41_2_, this_.numregistro as numregis7_41_2_, this_.produtor_idprodutor as produtor9_41_2_, this_.raca_idraca as raca10_41_2_, this_.sexo as sexo41_2_, produtor2_.idprodutor as idprodutor34_0_, produtor2_.localidade as localidade34_0_, produtor2_.municipio as municipio34_0_, produtor2_.nome as nome34_0_, produtor2_.propriedade as propried5_34_0_, raca3_.idraca as idraca35_1_, raca3_.descricao as descricao35_1_ from public.animal this_ inner join public.produtor produtor2_ on this_.produtor_idprodutor=produtor2_.idprodutor inner join public.raca raca3_ on this_.raca_idraca=raca3_.idraca where this_.produtor_idprodutor=? and not exists (select 1 from public.mortalidade where this_.idanimal=animal_idanimal)

O primeiro ou o segundo fica melhor??

aparentemente os dois geraram selects semelhantes, ai vai de vc testar o desempenho.