[Resolvido] @PostPersist não funciona

19 respostas
B

Pessoal, estou tentando utilizar pela primeira vez o ‘gatilho’ @PostPersist, mas ele não está funcionando.
Não ocorre nenhum erro, não acontece nada (coloquei um System.out.println()) pra testar).

Na minha entidade Usuario, coloquei a anotação @EntityListeners(logs.LogsListener.class).

Então, criei um arquivo chamado LogsListener, assim:

package logs;

import entities.Usuario;
import javax.persistence.PostPersist;


public class LogsListener {

    @PostPersist
    public void teste(Usuario usuario) {
        System.out.println(" - gatilho !");
    }

}

E um arquivo para testar:

package main;

import entities.Usuario;
import factory.HibernateConfig;
import java.sql.SQLException;
import org.hibernate.Session;

public class Main {

    public static void main(String[] args) throws SQLException {
        Session se = HibernateConfig.open();      
        
        se.beginTransaction();
        se.persist(new Usuario("bruno", "cobra"));
        se.getTransaction().commit();

        HibernateConfig.close();
    }

}

Estou utilizando o HSQLDB. Alguém sabe o que devo fazer para funcionar o listener?

19 Respostas

tebosoftware

O metodo que for ser anotado pelo @PostPersist não deve ter parametros.

pois ele é feito para validar o objeto que esta sendo gravado naquele instante… e fica na mesma classe que vai se persistir

Lavieri

tebosoftware:
O metodo que for ser anotado pelo @PostPersist não deve ter parametros.

pois ele é feito para validar o objeto que esta sendo gravado naquele instante… e fica na mesma classe que vai se persistir

nop, existem 2 modos de fazer uma é na propria entidade, e sem parametros, outro é em uma classe que faz auditoria, e essa leva como parametro a propria entdidade

como ele falou que colocou na entidade

@EntityListeners(logs.LogsListener.class)

então deveria funcionar

so pra efeito de teste, anota tb com @PrePersist, @PostUpdate, @PreUpdate

o dado esta efetivamente sendo incluido na tabela ?

B

Pois é cara, eu incluí todas as anotações @Pre[…] e @Post[…] possíveis, mas o meu System.out.println não foi executado em momento algum… Testei selects, inserts, deletes e updates… não tenho nem ideia do que pode estar ocorrendo…

Lavieri

linka tua classe Usuario … e me fala c o banco de dados esta sofrendo as alterações ?

B

linka tua classe Usuario … e me fala c o banco de dados esta sofrendo as alterações ?

Não entendi o que tu quis dizer com isso… poderia ser mais específico? :?

Ps.: as inserções, exclusões, alterações e seleções estão funcionando perfeitamente, ocorrem no banco de dados. A única coisa que não está funcionando é o gatilho, que no exemplo simplesmente lança uma mensagem através de System.out.println()

Lavieri

era isso que queria sabe, a outra coisa foi que pedi pra tu colocar o código da tua Entidade Usuario…

tenta passar o gatilho pra dentro da Entidade…

B

Já havia tentado o gatilho dentro da Entidade, e ele também não é executado.
Classe da Entidade:

package confip.entities;

import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
//import javax.persistence.EntityListeners;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.PostPersist;
import javax.persistence.Table;


@Entity
//@EntityListeners( value = confip.listeners.log.LogsListener.class )
@Table( name = "usuarios" )
public class Usuario implements Serializable {

    @Column( name = "id" )
    @GeneratedValue
    @Id
    private int id;
    @Column( length   = 12
           , name     = "username"
           , nullable = false
           , unique   = true )
    private String username;
    @Column( length   = 8
           , name     = "password"
           , nullable = false )
    private String password;


    public Usuario() {}
    public Usuario(String username, String password) {
        setPassword(password);
        setUsername(username);
    }


    @PostPersist
    public void teste() {
        System.out.println(" - teste gatilho");
    }

    
    public int getId() { return id; }
    public void setId(int id) { this.id = id; }

    public String getPassword() { return password; }
    public void setPassword(String password) { this.password = password; }

    public String getUsername() { return username; }
    public void setUsername(String username) { this.username = username; }


    @Override
    public String toString() {
        return "[id="+getId()+", username="+getUsername()+"]";
    }

}
S

Estou com o mesmo problema no @PreRemove. Já fiz algumas pesquisas no Google e aparentemente o código está correto.
Se conseguir resolver o problema, por favor coloque aqui a solução :slight_smile:

PS: Eu tou usando Postgres…

B

scheide:
Estou com o mesmo problema no @PreRemove. Já fiz algumas pesquisas no Google e aparentemente o código está correto.
Se conseguir resolver o problema, por favor coloque aqui a solução :slight_smile:

PS: Eu tou usando Postgres…

Pois é cara, meu código também está correto (ao menos ninguém daqui disse que não hehe). Eu já estava achando que fosse algo com o HSQLDB, mas já que disseste que está com problema semelhante no Postgres, a gente deve estar esquecendo de algum detalhe (e que inclusive não gera erros, infelizmente)… :?

Alguém tem alguma ideia?

Lavieri

bom... so pra desencargo de consiencia... eu fui testar os trigger aqui, peguei minha entidade Cidade... e botei uns trigger só com Print

public class Cidade implements Serializable {

    //... metodos da classe....
  
    @Override
    public int hashCode() {
        int hash = 0;
        hash += (id != null ? id.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof Cidade)) {
            return false;
        }
        Cidade other = (Cidade) object;
        if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "br.com.superlocar.model.entity.Cidade[id=" + id + "]";
    }

    @PostPersist
    public void postPersist() {
        System.out.println("postPersist: " + getNome());
    }

    @PrePersist
    public void prePersist() {
        System.out.println("prePersist: " + getNome());
    }

    @PreRemove
    public void preRemove() {
        System.out.println("preRemove: " + getNome());
    }

    @PostRemove
    public void postRemove() {
        System.out.println("postRemove: " + getNome());
    }
}

....

depois disso fiz um pequeno main, persissindo e removendo do banco de dados...

public class NewMain {
    private static EntityManager entityManager;
    
    public static void main(String[] args) {
        Estado paraiba = (Estado)getEntityManager()
                .createNamedQuery("Estado.findByNome")
                .setParameter("nome", "Paraíba")
                .getSingleResult();

        Cidade pqpDoSul = new Cidade();
        pqpDoSul.setEstado(paraiba);
        pqpDoSul.setNome("Cidade pre teste");


        System.out.println("\nTestando removendo antes do commit");
        getEntityManager().getTransaction().begin();
        getEntityManager().persist(pqpDoSul);
        getEntityManager().remove(pqpDoSul);
        System.out.println("Ate aqui só pre");
        getEntityManager().getTransaction().commit();
        //Aqui como não fecha a tranzação não chega nem aos Post so rola os Pre

        pqpDoSul.setNome("Cidade pre e post teste");
        System.out.println("\nTestando commitando o persist");
        getEntityManager().getTransaction().begin();
        getEntityManager().persist(pqpDoSul);
        System.out.println("Ate aqui só pre");
        getEntityManager().getTransaction().commit();
        System.out.println("Agora foi persistido");
        //aqui tem tanto o pre persist como o post

        System.out.println("Id da cidade: " + pqpDoSul.getId());

        System.out.println("\nTestando commitando o remove");
        getEntityManager().getTransaction().begin();
        getEntityManager().remove(pqpDoSul);
        System.out.println("Ate aqui só pre");
        getEntityManager().getTransaction().commit();
        System.out.println("Agora foi removido");
        //aqui tem tanto o pre remove como pos

        getEntityManager().close();
    }

    public static synchronized EntityManager getEntityManager() {
        if (entityManager == null) {
            entityManager = java.beans.Beans.isDesignTime() ? 
                null :
                javax.persistence.Persistence
                    .createEntityManagerFactory("Entity_Super_Locar_2PU")
                    .createEntityManager();
        }
        return entityManager;
    }
}

a saido do console foi perfeita... ele imprimiu tudo bonitinho...

Testando removendo antes do commit
prePersist: Cidade pre teste
preRemove: Cidade pre teste
Ate aqui só pre

Testando commitando o persist
prePersist: Cidade pre e post teste
Ate aqui só pre
postPersist: Cidade pre e post teste
Agora foi persistido
Id da cidade: 15572

Testando commitando o remove
preRemove: Cidade pre e post teste
Ate aqui só pre
postRemove: Cidade pre e post teste
Agora foi removido
B

A única diferença existente é que eu utilizo Session e tu, EntityManager…
Infelizmente, deve ser esse o problema, pois o único local da documentação do Hibernate onde encontrei menção sobre Callbacks foi onde fala de EntityManager (http://www.hibernate.org/hib_docs/entitymanager/reference/en/html/).

Por favor, alguém me diga que isso que eu falei é uma tremenda bobagem e que o problema não é esse, hehe… :!:

Lavieri

a outra diferença é que nesse exmplo especifico é com TopLink e não com Hibernate, porem, ja fiz com hibernate antes e tb dava certo… vou fazer com Hibernate Session e ver no q da… jaja posto aqui

Lavieri

bruno_cobra:
A única diferença existente é que eu utilizo Session e tu, EntityManager…
Infelizmente, deve ser esse o problema, pois o único local da documentação do Hibernate onde encontrei menção sobre Callbacks foi onde fala de EntityManager (http://www.hibernate.org/hib_docs/entitymanager/reference/en/html/).

Por favor, alguém me diga que isso que eu falei é uma tremenda bobagem e que o problema não é esse, hehe… :!:

Bom testado e o resultado é…

Com session do Hibernate, não faz os @Post e @Pre
Usando o EntityManager do Hibernate … ele faz diretinho…

é a vida…

fazer um entity manager é simples

basta criar um arquivo: persistence.xml dentro da pasta META-INF <?xml version="1.0" encoding="UTF-8"?> <persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"> <persistence-unit name="EntityManger_Nome_da_Sua_Escolha" transaction-type="RESOURCE_LOCAL"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <class>br.com.seuSite.model.entity.Cidade</class> <class>br.com.seuSite.model.entity.Estado</class> <class>br.com.seuSite.model.entity.Pais</class> <properties> <property name="hibernate.connection.username" value="root"/> <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/> <property name="hibernate.connection.password" value="root"/> <property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/suBancoDeDados"/> <property name="hibernate.cache.provider_class" value="org.hibernate.cache.NoCacheProvider"/> </properties> </persistence-unit> </persistence>

e para invocar o EntityManager, basta fazer uma classe utilitária com um método assim… private static EntityManager enityManager public static synchronized EntityManager getEntityManager() { if (entityManager == null) { entityManager = java.beans.Beans.isDesignTime() ? null : javax.persistence.Persistence .createEntityManagerFactory("EntityManger_Nome_da_Sua_Escolha") .createEntityManager(); } return entityManager; }

é isso…

Ps.: O NetBeans tem mecanismos para criar os entitymanager sem esforço

B

Valeu Lavieri, sua ajuda foi de grande valia para mim, muito obrigado mesmo.

Então você recomenda que eu utilize o EntityManager e esqueça meus Session? Confesso que não tenho muita “intimidade” com essa parte, mas até onde já li, é mais recomendado utilizar o Session…

Bom, vou dar uma pesquisada sobre isso assim que possível… valeu!

Lavieri
bruno_cobra:
Valeu Lavieri, sua ajuda foi de grande valia para mim, muito obrigado mesmo.

Então você recomenda que eu utilize o EntityManager e esqueça meus Session? Confesso que não tenho muita "intimidade" com essa parte, mas até onde já li, é mais recomendado utilizar o Session...

Bom, vou dar uma pesquisada sobre isso assim que possível... valeu!

que nada... pra tudo na vida existe uma solução auhahuauh =x

acabei de verificar aqui... as EntityManager do Hibernate, implementam um outra interface tb HibernateEntityManager link

logo vc não precisa trabalhar com a EntityManger (apesar de ser bem simples), se for do seu agrado vc pode trabalhar com a Session... o que vc precisa mesmo, é criar a factory de EntityManager, e pegar as session via EntityManager...

pra não ficar só na teoria vamos ao exemplo... crei essa classe aqui

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import org.hibernate.Session;
import org.hibernate.ejb.HibernateEntityManager;

/**
 *
 * @author Tomaz Lavieri
 */
public class EntityUtil {
    private static EntityManagerFactory entityManagerFactory;
    private static EntityManager entityManager;

    public static EntityManager getPublicEntityManager() {
        if (entityManager == null)
            entityManager = java.beans.Beans.isDesignTime() ?
                null :
                getEntityManagerFactory().createEntityManager();

        return entityManager;
    }

    public static EntityManager getNewEntityManager() {
        return getEntityManagerFactory().createEntityManager();
    }

    public static synchronized EntityManagerFactory getEntityManagerFactory() {
        if (entityManagerFactory == null) {
            entityManagerFactory = java.beans.Beans.isDesignTime() ?
                null :
                javax.persistence.Persistence
                    .createEntityManagerFactory("SuperLocar_Hibernate");
        }
        return entityManagerFactory;
    }
    
    public static Session getPublicSession() {
        return ((HibernateEntityManager)getPublicEntityManager()).getSession();
    }
    
    public static Session getNewSession() {
        return ((HibernateEntityManager)getNewEntityManager()).getSession();
    }
}

agora fica como vc ker usar =x

public static void main(String[] args) {
        Session session = EntityUtil.getNewSession();
        
        Estado paraiba = (Estado)session.load(Estado.class, 18);
        
        Cidade cidade = new Cidade();
        cidade.setEstadoId(paraiba);
        cidade.setNome("Cidade da Cidade");

        session.beginTransaction();
        session.persist(cidade);
        session.delete(cidade);
        session.getTransaction().commit();

    }
Um pedaço da classe Cidade
public class Ciade implements Serializable { //....
//....
    @PrePersist
    public void prePersist() {
        System.out.println("Pre persist na area: " + getNome());
    }
}

a resposta do console...

Pre persist na area: Cidade da Cidade

espero que assim vc resolva seu problema ^^ e se tiver conseguido, da um EDIT no titulo do topico com um [RESOLVIDO] ^^

..............

Ps.: com session só funcionara com hibernate, com EntityManager, fucionara com qualquer framework de persistencia que implemente EJB

B

E funcionou agora… portanto, muito obrigado Lavieri, tua ajuda resolveu meu problema, mas é uma pequena que eu tenha que criar o entitymanager… mas ao menos funciona!

Valeu

Lavieri

bruno_cobra:
E funcionou agora… portanto, muito obrigado Lavieri, tua ajuda resolveu meu problema, mas é uma pequena que eu tenha que criar o entitymanager… mas ao menos funciona!

Valeu

^^ … mas pelo que conheço do hibernate, tenho certeza que existe alguma configuração do session factory, que liga os triggers, se vc descobrir isso, não vai mais precisar fazer isso ^^

Lavieri

bomo como eu tinha falado ^^ .... da pra fazer sem criar EntityManager.... assim como o EntityManager do Hibernate tem uma session... o EntityManagerFactory tem uma SessionFactory... por isso da pra fazer asssim

import javax.persistence.Persistence;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.ejb.HibernateEntityManagerFactory;

/**
 *
 * @author Tomaz Lavieri
 */
public class EntityUtil2 {
    private static SessionFactory sessionFactory;
    private static Session publicSession;

    public static synchronized SessionFactory getSessionFactory() {
        if (sessionFactory == null) {
            sessionFactory = java.beans.Beans.isDesignTime() ?
                null :
                ((HibernateEntityManagerFactory)Persistence
                    .createEntityManagerFactory("SuperLocar_Hibernate"))
                    .getSessionFactory();
        }
        return sessionFactory;
    }

    public static Session getPublicSession() {
        if (publicSession == null)
            publicSession = getSessionFactory().openSession();
        return publicSession;
    }

    public static Session getNewSession() {
        return getSessionFactory().openSession();
    }
}

funciona tb e so trabalha com Session e SessionFactory

B

Valeu cara, funcionou perfeitamente!

Muito obrigado.

Criado 17 de março de 2009
Ultima resposta 24 de mar. de 2009
Respostas 19
Participantes 4