Curso de Linguagem Java 2º Semestre - 2007 Marcos Mendes 1 JPA - Java Persistence API (Beans de Entidade) Referência Bibliográfica: Enterprise JavaBeans 3.0 Bill Burke & Richard Monson Editora. Prentice Hall Desenvolvendo Aplicações Web com JSP, Servlets, JSF, Hibernate, EJB 3 e Ajax Edson Gonçalves Editora Ciência Moderna Revista JavaMagazine edições 39 e 44 Revista MundoJava edição 24 Página da Sun sobre a tecnologia JPA http://java.sun.com/javaee/technologies/persistence.jsp 2 JPA – Java Persistence API Arquitetura Aplicação Java Java Persistence API Provedor JPA API JDBC Driver JDBC Banco De Dados 3 JPA – Java Persistence API Conceitos Parte integrante da JavaEE 5 Disponível a partir da Java5 Definida na JSR220 – Enterprise JavaBeans 3.0 Padroniza o Mapeamento Objeto Relacional Não depende de Container para funcionar Baseada no conceito de POJOs (Plain Old Java Object) Utiliza amplamente Annotations (Progamação Declarativa) Pacote javax.persistence 4 JPA – Java Persistence API Os objetos persistentes são denominados Entities(Entidades) Estas Entidades devem possuir um identificador(chave primária) e um construtor sem parâmetros. Unidade de Persistência Conjunto de classes mapeadas para um banco de dados relacional. Esse mapeamento é feito através de um arquivo descritor de implantação chamado persistence.xml que é gravado na pasta META-INF e que pode conter a configuração de várias unidades de persistência. Contexto de Persistência(Persistence Context) Ambiente (sessão) que envolve o conjunto de instâncias de entidades gerenciadas pelo Entity Manager. 5 JPA – Java Persistence API Gerenciador de Entidades (Entity Manager) javax.persistence.EntityManager Serviço que gerenciará o conjunto de entidades registradas dentro de um contexto. Monitorando as alterações feitas nos objetos deste contexto de persistência, gravando assim essas alterações no banco de dados. Provedor de Persistência (Persistence Provider) É como se fosse um driver JPA para uma determinada ferramenta de mapeamento objeto-relacional. Mais específicamente, é a classe que implementa a interface javax.persistence.PersistenceProvider São alguns exemplos de fornecedores de provedores de persistência: Oracle TopLink, Hibernate, Kodo, Open JPA, etc. 6 JPA – Java Persistence API Ciclo de Vida / Estados de um objeto Objeto não existe new find( ) clear( ) ou quando o EntityManager é fechado DETACHED NEW merge( ) persist( ) MANAGED remove( ) REMOVED Garbage Collector 7 JPA – Java Persistence API Mapeamento Básico de Entidades É feito com o uso de anotações nas classes persistentes. @Entity – Marca uma classe como entidade persistente. Esta classe deve possuir um construtor sem parâmetros. @Table – Define o nome da Tabela onde os objetos serão persistidos. @Id – Define o atributo que constitui a chave primária. @GeneratedValue – Define um campo auto-incremento. @Column – Define o nome da coluna onde o atributo será salvo. @Transient – Define que um atributo não será salvo no banco de dados. 8 JPA – Java Persistence API Exemplo de Entidade import javax.persistence.*; @Entity @Table(name = "Aluno") public class Aluno { @Id @GeneratedValue (strategy=GenerationType.IDENTITY) @Column(name = "id", nullable = false, columnDefinition = "integer") private int id; @Column(name = "nome", length = 50, nullable = false) private String nome; @Column(name = "ra") private long ra; //getters e setters omitidos } 9 JPA – Java Persistence API Exemplo de Entidade (usando mapeamentos padrão) import javax.persistence.*; @Entity public class Aluno { @Id @GeneratedValue private int id; private String nome; private long ra; //getters e setters omitidos } 10 JPA – Java Persistence API No código da aplicação que utiliza classes persistentes: Criar um Gerenciador de Entidades através de uma fábrica: EntityManagerFactory emf = Persistence.createEntityManagerFactory("unidade"); EntityManager em = emf.createEntityManager(); Iniciar uma Transação: em.getTransaction().begin(); Criar uma Entidade: Entidade e = new Entidade(); Persistir uma Entidade: em.persist(e); Localizar uma Entidade: Entidade e = em.find(Entidade.class, chave); Sincronizar uma Entidade: e = em.merge(e); Eliminar uma Entidade: em.remove(e); Encerrar uma Transação: em.getTransaction().commit(); 11 JPA – Java Persistence API Interface EntityManager (alguns métodos) void persist(Object objeto) Persiste uma entidade, torna-a gerenciada pelo Gerenciador de Entidades. Qualquer alteração na entidade será refletida no banco de dados. <T> T merge(T entidade) Sincroniza os dados no banco de dados com os atributos da entidade. Retorna um objeto gerenciado(managed). Não pode ser usado em um objeto REMOVED. void refresh(Object entidade) Sincroniza os atributos na entidade com os dados do banco de dados. void remove(Object entidade) Remove uma entidade do banco de dados. <T> T find(Class<T> classeEntidade, Object chavePrimária) Retorna uma entidade(MANAGED) através de sua chave primária. Retorna null caso a chave não seja encontrada. 12 JPA – Java Persistence API Query createQuery(String sql) Cria uma consulta dinâmica. Query createNamedQuery(String nomeConsulta) Cria uma consulta nomeada. EntityTransaction getTransaction( ) Retorna a transação do EntityManager. Interface EntityManager (alguns métodos) void begin( ) Inicia uma transação. void commit( ) Encerra uma transação, gravando quaisquer alterações no banco de dados. void rollback( ) Desfaz quaisquer alterações desde o início da transação. 13 JPA – Java Persistence API Exemplo de Aplicação JavaSE usando Oracle TopLink Baixe o Oracle TopLink através do link: http://www.oracle.com/technology/products/ias/toplink/jpa/download.html Coloque o arquivo baixado em uma pasta de trabalho e execute o seguinte comando nesta pasta: java -jar glassfish-persistence-installer-v2-bXX.jar Isto irá criar uma pasta chamada glassfish-persistence contendo o arquivo de licença, README e as bibliotecas TopLink Essentials: 3RD-PARTY-LICENSE.txt CDDLv1.0.txt README toplink-essentials-agent.jar toplink-essentials.jar 14 JPA – Java Persistence API Crie um projeto (Java5 ou superior) e adicione os arquivos .jar mencionados anteriormente, no classpath, para que se possa utilizar o Oracle TopLink. Não esqueça de adicionar também o .jar do driver JDBC. Crie a classe persistente chamada Aluno descrita abaixo: package modelo; import javax.persistence.*; @Entity public class Aluno { @Id @GeneratedValue (strategy=GenerationType.IDENTITY) private int id; private String nome; private long ra; private double ms1; private double ms2; //getters e setters omitidos } 15 JPA – Java Persistence API Crie o arquivo persistence.xml na pasta META-INF em seu projeto. <?xml version="1.0" encoding="UTF-8"?> <persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"> <persistence-unit name="teste"> <provider> oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider </provider> <class>modelo.Aluno</class> <properties> <property name="toplink.logging.level" value="INFO" /> <property name="toplink.jdbc.driver" value="com.mysql.jdbc.Driver" /> 16 JPA – Java Persistence API <property name="toplink.jdbc.url" value="jdbc:mysql://127.0.0.1:3306/uniban" /> <property name="toplink.jdbc.user" value="root" /> <property name="toplink.jdbc.password" value="admin" /> <property name="toplink.ddl-generation" value="create-tables" /> </properties> </persistence-unit> </persistence> Crie o banco de dados de teste com o nome uniban 17 JPA – Java Persistence API Inclusão - Crie a classe da aplicação chamada CriaAluno e a execute. package negocio; import modelo.*; import javax.persistence.*; public class CriaAluno { public static void main(String[] args) { EntityManagerFactory emf = Persistence.createEntityManagerFactory("teste"); EntityManager em = emf.createEntityManager(); em.getTransaction().begin(); Aluno a = new Aluno(); a.setNome("Maria"); a.setRa(123456789); a.setMs1(5.5); a.setMs2(4.5); em.persist(a); //Torna o objeto MANAGED em.getTransaction().commit(); em.close(); emf.close(); System.out.println("id do aluno persistido: " + a.getId()); } } 18 JPA – Java Persistence API Implantação da Aplicação. Na pasta raiz do seu projeto, crie um arquivo texto chamado manifest.txt com o seguinte conteúdo: Main-class: CriaAluno Class-path: mysql-connector-java-5.0.6-bin.jar toplink-essentials.jar toplink-essentials-agent.jar Obs.: Deve haver um espaço em branco após os dois pontos de cada parâmetro; deve haver uma linha em branco no final do arquivo; os arquivos .jar devem ser separados por espaços em branco e devem estar numa única linha no arquivo. No prompt de comando, na pasta raiz do seu projeto, digite a seguinte linha de comando: jar cvfm teste.jar manifest.txt *.class model/*.class META-INF/* Será gerado um arquivo chamado teste.jar que contém as classes da aplicação. Copie os arquivos .jar do Oracle TopLink e o .jar do driver JDBC para a pasta onde estiver o arquivo teste.jar. Para executar a aplicação, digite a seguinte linha de comando: java -jar teste.jar 19 JPA – Java Persistence API Automatização de deploy com o Apache Ant Baixe o Ant (arquivo: apache-ant-1.7.0-bin.zip) do site: http://ant.apache.org Descompacte o arquivo na pasta raiz do hd. Renomeie a pasta para "ant". Crie uma variável de ambiente chamada "ANT_HOME" contendo o caminho da pasta de instalação do ant: "set ANT_HOME=c:\ant" Inclua o caminho "%ANT_HOME%\bin" no path do sistema. Crie um arquivo build.xml na pasta raiz do seu projeto com o conteúdo a seguir. 20 JPA – Java Persistence API <?xml version="1.0" encoding="iso-8859-1" ?> <project name= "teste" default= "implantaJar" > <target name="implantaJar" depends="criaJar"> <copy file="${jarFile}" todir="${deployDir}" overwrite="yes"/> </target> <target name="criaJar" depends="compila"> <jar destfile="${jarFile}" > <fileSet dir="." includes="*.class" /> <fileSet dir="./model" includes="*.class" /> <fileSet dir="./META-INF" includes="**" /> </jar> </target> 21 JPA – Java Persistence API <target name="compila" depends="ambiente"> <javac srcdir="." destdir="."> <classpath path=" lib/toplink-essentials.jar" /> <classpath path=" lib/toplink-essentials-agent.jar" /> </javac> <javac srcdir="./model" destdir="./model"> <classpath path=" lib/toplink-essentials.jar" /> <classpath path=" lib/toplink-essentials-agent.jar" /> </javac> </target> <target name="ambiente" > <property name="jarFile" value= "./teste.jar" /> <property name="deployDir" value="." /> </target> </project> 22 JPA – Java Persistence API Integrando o ANT com o Eclipse Selecione o menu "Project"; Selecione "properties"; Selecione "Builders"; Clique em "new"; Escolha "Ant Build"; Em "Name Buildfile" clique em xxx e selecione o arquivo de build criado anteriormente; Com o build selecionado clique no botão "up" até que o "ant build" apareça em primeiro lugar na lista. 23 JPA – Java Persistence API Busca – Localiza uma entidade através da chave primária. package negocio; import modelo.*; import javax.persistence.*; public class BuscaAluno { public static void main(String[] args) { EntityManagerFactory emf = Persistence.createEntityManagerFactory("teste"); EntityManager em = emf.createEntityManager(); Aluno a = em.find(Aluno.class, 3); // Retorna um objeto MANAGED if (a != null) { System.out.println("RA: " + a.getRa()); System.out.println("Nome: " + a.getNome()); //Objeto está MANAGED, porém, qualquer alteração NÃO será //refletida no banco de dados, pois não há Transação. a.setNome("Novo Nome"); } else { System.out.println("Aluno não encontrado"); } } } 24 JPA – Java Persistence API Alteração – Localiza uma entidade através da chave primária e altera seu estado. package negocio; import modelo.*; import javax.persistence.*; public class AlteraAluno { public static void main(String[] args) { EntityManagerFactory emf = Persistence.createEntityManagerFactory("teste"); EntityManager em = emf.createEntityManager(); em.getTransaction().begin(); Aluno a = em.find(Aluno.class, 1); //Retorna um objeto MANAGED if (a != null) { a.setNome("Novo Nome"); a.setRa(987654321); a.setMs1(2.5); a.setMs2(3.5); System.out.println("id do aluno alterado: " + a.getId()); } em.getTransaction().commit(); em.close(); emf.close(); } } 25 JPA – Java Persistence API Exclusão - Localiza uma entidade através da chave primária e a exclui. package negocio; import modelo.*; import javax.persistence.*; public class ExcluiAluno { public static void main(String[] args) { EntityManagerFactory emf = Persistence.createEntityManagerFactory("teste"); EntityManager em = emf.createEntityManager(); em.getTransaction().begin(); Aluno a = em.find(Aluno.class, 8); if (a != null) { em.remove(a); /*Objeto torna-se REMOVED, qualquer alteração não será refletida no banco de dados.*/ System.out.println("Aluno excluído: " + a.getId()); System.out.println(" " + a.getNome()); } else { System.out.println("Aluno não encontrado"); } em.getTransaction().commit(); em.close(); emf.close(); } } 26 JPA – Java Persistence API Sincronização - Localiza uma entidade através da chave primária, encerra o EntityManager, altera o estado da entidade e a sincroniza no banco de dados. package negocio; import modelo.*; import javax.persistence.*; public class SincronizaAluno { public static void main(String[] args) { EntityManagerFactory emf = Persistence.createEntityManagerFactory("teste"); EntityManager em = emf.createEntityManager(); Aluno a = em.find(Aluno.class, 9); em.close(); if (a != null) { System.out.println("Nome: " + a.getNome()); a = mudaDados(a); em = emf.createEntityManager(); em.getTransaction().begin(); em.merge(a); //Sincroniza o estado da entidade no banco de dados em.getTransaction().commit(); System.out.println("Novo Nome: " + a.getNome()); } else { System.out.println("Aluno não encontrado"); } } private static Aluno mudaDados(Aluno a) { a.setNome("Juliana"); return a; } } 27 JPA – Java Persistence API Consultas As consultas são criadas usando-se tanto a linguagem de consulta EJB Query Language (também chamada de JPA QL) como a SQL nativa. A EJB QL é semelhante à SQL, só que orientada a objetos e portável para diferentes implementações de bancos de dados. São executadas por meio da interface javax.persistence.Query que é muito parecida com a interface java.sql.PreparedStatement. Essa interface Query é obtida em tempo de execução a partir do gerenciador de entidade. As consultas podem ser criadas dinamicamente em tempo de execução ou pré-declaradas por meio de anotações nas classes persistentes ou através de XML. 28 JPA – Java Persistence API Interface Query (javax.persistence.Query) Alguns Métodos List getResultList ( ) Executa uma consulta e retorna uma coleção de resultados. Object getSingleResult ( ) Executa uma consulta e retorna um único resultado. int executeUpdate ( ) Executa um comando de atualização(insert, update ou delete) e retorna o número de linhas afetadas no banco de dados. Query setMaxResults (int máximo) Define o número máximo de entidades que deve ser retornado na consulta. 29 JPA – Java Persistence API Query setFirstResult (int início) Define o número da linha inicial que irá compor o resultado da consulta. void setParameter (String nome, Object valor) Define o valor de um parâmetro através de seu nome. Query setParameter (String nome, Date valor, TemporalType tipo) Define o valor de um parâmetro do tipo data através de seu nome. Query setParameter (int posição, Object valor) Define o valor de um parâmetro através de sua posição. Query setParameter (int posição, Date valor, TemporalType tipo) Define o valor de um parâmetro do tipo data através de sua posição. 30 JPA – Java Persistence API Consultas Dinâmicas São criadas pelo gerenciador de entidades através do método createQuery(). Consulta que retorna um único resultado: try { Query consulta = em.createQuery( "Select a from Aluno a where a.ra = :ra"); consulta.setParameter("ra", 123456789); Aluno a = (Aluno) consulta.getSingleResult(); System.out.println("RA: " + a.getRa()); System.out.println("Nome: " + a.getNome()); } catch(NoResultException ex) { System.out.println("Aluno não encontrado"); } catch(NonUniqueResultException ex) { System.out.println("Mais que um resultado encontrado"); } 31 JPA – Java Persistence API Os parâmetros da consulta são ajustados através do método setParameter( ) e podem ser indicados através de duas formas: Identificados, utilizando-se : (dois pontos) e um nome; Query consulta = em.createQuery( "Select a from Aluno a where a.ra = :ra and a.nome = :nome ); consulta.setParameter("ra", 123456789); consulta.setParameter("nome", "Maria"); Seqüenciados, utilizando-se ? (interrogação) e um número sequencial. Query consulta = em.createQuery( "Select a from Aluno a where a.ra = ?1 and a.nome = ?2 ) consulta.setParameter(1, 123456789); consulta.setParameter(2, "Maria"); 32 JPA – Java Persistence API package negocio; import modelo.*; import javax.persistence.*; Consulta que retorna um único resultado public class BuscaPorRA { public static void main(String[] args) { EntityManagerFactory emf = Persistence.createEntityManagerFactory("teste"); EntityManager em = emf.createEntityManager(); try { Query consulta = em.createQuery("Select a from Aluno a where a.ra = :ra"); consulta.setParameter("ra", 123456789); Aluno a = (Aluno)consulta.getSingleResult(); System.out.println("RA: " + a.getRa()); System.out.println("Nome: " + a.getNome()); } catch(NoResultException ex) { System.out.println("Aluno não encontrado"); } catch(NonUniqueResultException ex) { System.out.println("Mais que um resultado encontrado"); } em.close(); emf.close(); } } 33 JPA – Java Persistence API Consulta que retorna os resultados em uma java.util.List: Query consulta = em.createQuery( "Select a from Aluno a where a.ms1 > :media"); consulta.setParameter("media", 5); List <Aluno>alunos = consulta.getResultList(); if (!alunos.isEmpty()) { for (Aluno a : alunos) { System.out.println("Nome: " + a.getNome()); } } else { System.out.println("Alunos não encontrados"); } 34 JPA – Java Persistence API package negocio; Consulta que retorna uma import java.util.List; coleção de resultados import modelo.*; import javax.persistence.*; public class ConsultaPorMedia { public static void main(String[] args) { EntityManagerFactory emf = Persistence.createEntityManagerFactory("teste"); EntityManager em = emf.createEntityManager(); Query consulta = em.createQuery( "Select a from Aluno a where a.ms1 > :media"); consulta.setParameter("media", 5); List <Aluno>alunos = consulta.getResultList(); if (!alunos.isEmpty()) { for (Aluno a : alunos) { System.out.println("Nome: " + a.getNome()); } } else { System.out.println("Alunos não encontrados"); } } } em.close(); emf.close(); 35 JPA – Java Persistence API Consulta que utiliza um java.util.Date como parâmetro: Query consulta = em.createQuery( "Select a from Aluno a where a.DataMatricula = :data"); consulta.setParameter("data", new java.util.Date, TemporalType.DATE); List <Aluno>alunos = consulta.getResultList(); if (!alunos.isEmpty()) { for (Aluno a : alunos) { System.out.println("Nome: " + a.getNome()); } } else { System.out.println("Alunos não encontrados"); } 36 JPA – Java Persistence API Consulta com paginação de resultados: public static List getAlunos(int maximo, int inicio) { Query consulta = em.createQuery("Select a from Aluno a"); return consulta.setMaxResults(maximo). setFirstResult(inicio). getResultList(); } 37 JPA – Java Persistence API package negocio; import modelo.*; import javax.persistence.*; import java.util.List; public class ConsultaPaginada { static EntityManagerFactory emf; static EntityManager em; Consulta com paginação de resultados public static List getAlunos(int maximo, int inicio) { Query consulta = em.createQuery("Select a from Aluno a"); return consulta.setMaxResults(maximo). setFirstResult(inicio). getResultList(); } 38 JPA – Java Persistence API public static void main(String[] args) { emf = Persistence.createEntityManagerFactory("teste"); em = emf.createEntityManager(); int inicio = 1, maximo = 3; int pagina = 1; List <Aluno> alunos = null; do { alunos = getAlunos(maximo, inicio); if (!alunos.isEmpty()) { System.out.println("Pág. " + pagina); for (Aluno a : alunos) { System.out.println("Nome: " + a.getNome()); } } inicio += maximo; pagina++; } while (!alunos.isEmpty()); em.close(); emf.close(); } } 39 JPA – Java Persistence API Consultas Nomeadas (Identificadas) Na entidade Na aplicação São consultas pré-definidas na classe da entidade e podem ser reutilizadas em diferentes pontos da sua aplicação, facilitando assim sua manutenção. São declaradas através das anotações @NamedQueries(define um array de consultas nomeadas) e @NamedQuery(define uma consulta nomeada). São criadas pelo gerenciador de entidades através do método createNamedQuery(). @NamedQueries({ @NamedQuery(name = "consultaPorRA", query = "Select a from Aluno a where a.ra = :ra"), @NamedQuery(name = "consultaPorMedia", query = "Select a from Aluno a where a.ms1 > :media") }) Query consulta = em.createNamedQuery("consultaPorMedia"); consulta.setParameter("media", 5); 40 JPA – Java Persistence API Utilização de package modelo; Consulta Nomeada import javax.persistence.*; @NamedQueries( { Classe da Entidade @NamedQuery(name = "buscaPorRA", query = "Select a from Aluno a where a.ra = :ra"), @NamedQuery(name = "consultaPorMedia", query = "Select a from Aluno a" + " where (a.ms1*0.3 + a.ms2*0.7) > :media"), @NamedQuery(name = "aumentaMedia", query = "Update Aluno set ms1 = ms1 + :bonus"), }) @Entity public class Aluno { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private int id; private String nome; private long ra; private double ms1; private double ms2; // getters e setters omitidos } 41 JPA – Java Persistence API Utilização de package negocio; import modelo.*; Consulta Nomeada import javax.persistence.*; Classe da Aplicação import java.util.List; public class ConsultaNomeada { public static void main(String[] args) { EntityManagerFactory emf = Persistence.createEntityManagerFactory("teste"); EntityManager em = emf.createEntityManager(); Query consulta = em.createNamedQuery("consultaPorMedia"); consulta.setParameter("media", 5); } } List <Aluno>alunos = consulta.getResultList(); if (!alunos.isEmpty()) { for (Aluno a : alunos) { System.out.println("Nome: " + a.getNome()); } } else { System.out.println("Alunos não encontrados"); } em.close(); emf.close(); 42 JPA – Java Persistence API Alterações em Lote São criadas pelo gerenciador de entidades da mesma forma que as consultas. Podem ser tanto dinâmicas como nomeadas. São executadas através do método executeUpdate() que retorna o número de linhas afetadas. Query alteracao = em.createQuery( "Update Aluno set ms1 = ms1 + :bonus"); alteracao.setParameter("bonus", 0.5); int qtdAlunos = alteracao.executeUpdate(); 43 JPA – Java Persistence API package negocio; import javax.persistence.*; Alteração em lote public class AumentaMedia { public static void main(String[] args) { EntityManagerFactory emf = Persistence.createEntityManagerFactory("teste"); EntityManager em = emf.createEntityManager(); em.getTransaction().begin(); Query alteracao = em.createQuery( "Update Aluno set ms1 = ms1 + :bonus"); alteracao.setParameter("bonus", 0.5); int qtdAlunos = alteracao.executeUpdate(); System.out.println(qtdAlunos + " Alunos bonificados"); } } em.getTransaction().commit(); em.close(); emf.close(); 44 JPA – Java Persistence API Eventos de Retorno de Chamada Através das anotações abaixo, pode-se definir métodos que serão executados em resposta a um evento do ciclo de vida de uma entidade. @PrePersist Define o método a ser executado logo após a uma chamada de EntityManager.persist(). @PostPersist Define o método a ser executado após a inserção no banco de dados. @PostLoad Define o método a ser executado após a uma chamada de EntityManager.find(), EntityManager.refresh(), ou quando uma consulta EJB QL é executada. 45 JPA – Java Persistence API @PreUpdate Define o método a ser executado antes do estado de uma entidade ser sincronizado com o banco de dados. @PostUpdate Define o método a ser executado após o estado de uma entidade ser sincronizado, isso ocorre na confirmação de uma transação, após uma chamada a EntityManager.flush() ou sempre que o contexto de persistência atualizar o banco de dados. @PreRemove Define o método a ser executado após a uma chamada de EntityManager.remove(). @PostRemove Define o método a ser executado após a exclusão no banco de dados ser efetivada. Pesquise também sobre Ouvintes de entidade. 46 JPA – Java Persistence API package modelo; import java.io.*; import java.util.Date; import javax.persistence.*; Exemplo de Arquivo de Log @Entity public class Aluno { ... @PrePersist void prePersist() { try { FileOutputStream fos = new FileOutputStream("log.txt", true); String linha = "Aluno " + getNome() + " gravado em " + new Date() + "\n"; fos.write(linha.getBytes()); fos.close(); fos.close(); } catch (IOException e) { e.printStackTrace(); } } } 47 JPA – Java Persistence API Exemplo de Aplicação Swing com JPA 48