JPA (Java Persistence API) (kalinowski@ic.uff.br)
Agenda Conceitos básicos do JPA Mapeamento objeto relacional utilizando JPA Utilizando JPA para a persistência na prática EntityManager JPQL (Java Persistence Query Language) 2
Agenda Conceitos básicos do JPA Mapeamento objeto relacional utilizando JPA Utilizando JPA para a persistência na prática EntityManager JPQL (Java Persistence Query Language) 3
Conceitos básicos do JPA JPA é uma abstração em cima do JDBC que torna possível ser independente do SQL Todas as classes e anotações da API JPA estão no pacote javax.persistence 4
Principais componentes do JPA ORM (Object-Relational Mapping) para a criação de objetos de domínio que podem ser persistidos (Entities) Uma API (EntityManager) para desempenhar operações de BD como Criar, Ler, Atualizar e Remover (CRUD) A linguagem de consulta de persistência Java (Java Persistence Query Language - JPQL) que permite recuperar dados com uma linguagem de consulta OO 5
O Conceito de Entidade Quando estamos mapeando objetos para um BD relacional, para persisti-los ou consultá-los o termo entidade deve ser usado Objetos são apenas mantidos em memória Entidades são objetos que são mantidas na memória durante um algum intervalo de tempo e, então persistidas no banco de dados Suportam herança, relacionamentos, etc. Desde que mapeados para o gerenciamento do JPA Uma vez persistidas, as entidades podem ser consultadas através da JPQL 6
Agenda Conceitos básicos do JPA Mapeamento objeto relacional utilizando JPA Utilizando JPA para a persistência na prática EntityManager JPQL (Java Persistence Query Language) 7
Mapeamento Objeto-Relacional O princípio do ORM é delegar a ferramentas externas (no nosso caso JPA) a tarefa de criar uma correspondência entre objetos e tabelas O mundo das classes, objetos e atributos podem, então, ser mapeados para BDs relacionais consistindo em tabelas, linhas e colunas O mapeamento proporciona uma visão orientada à objetos aos desenvolvedores que podem usar entidades em vez de tabelas de forma transparente 8
Mapeamento Objeto-Relacional Há uma diferença semântica significativa entre o modelo de classes de um projeto orientado a objetos e o modelo relacional. Assim, para que a persistência de objetos seja feita em um banco de dados relacional, é necessário proceder um mapeamento entre esses dois mundos. Diretriz: O mapeamento só deve ser visível na camada de persistência, isolando as classes de domínio do impacto da tecnologia de bancos de dados. Alternativas: Padrão DAO; Frameworks como JPA 9
Mapeamento Objeto-Relacional No mapeamento dos mundos de objetos e relacional, as seguintes questões devem ser abordadas: Mapeamento de Classes para Tabelas e de Objetos para Linhas; Mapeamento de Herança; Mapeamento de Relacionamentos entre Objetos. 10
Mapeamento de Classes para Tabelas e de Objetos para Linhas Quando não há herança, cada classe deve ser mapeada em uma tabela e cada instância da classe (objeto) em uma linha desta tabela. E as chaves primárias das Tabelas? Objetos têm identidade própria, independentemente dos valores de seus atributos. Que identificador devemos designar aos nossos objetos no banco de dados relacional? Verificar se há um atributo na classe com propriedade de identificação única e utilizá-lo, então, como chave primária. Caso não haja um atributo com tal característica, deverá ser criado um. 11
Mapeando Herança Existem três soluções razoavelmente aplicáveis para mapear a herança em um banco de dados relacional: 1) Utilizar uma tabela por classe na hierarquia, com chaves estrangeiras para a classe pai. 2) Utilizar uma tabela por classe filha na hierarquia. Cada tabela derivada para as classes concretas inclui tanto os atributos da classe quanto os de suas superclasses. Problemas? Possível redundância e inconsistência de dados. 3) Utilizar uma tabela para a classe pai com todos os atributos. As subclasses serão views da classe pai. Problemas? Possível redundância e inconsistência de dados. 12
Mapeando Relacionamentos É necessário transpor chaves entre tabelas para mapear relacionamentos. As regras válidas para o modelo relacional tem de ser aplicadas, tal como criar uma tabela adicional para mapear um relacionamento muitos-para-muitos. 13
Exemplo 14
Exemplo 15
Definição das Tabelas Alternativa 1 16
Definição das Tabelas Alternativa 2 (a princípio menos interessante) 17
Definição das Tabelas Alternativa 3 18
Exemplo 19
Definição das Tabelas 20
Exemplo 21
Definição das Tabelas 22
Mapeamento Objeto-Relacional Mas como o JPA mapeia objetos para um BD? Através de metadados! No JPA, metadados podem ser de dois tipos: Anotações: a classe é anotada com informações sobre como deve ser persistida Descritores XML: neste caso, o mapeamento é definido em um arquivo XML externo Podem ser usados em conjunto com anotações e oferecem a possibilidade de serem editados sem mudar o código Utiliza configuração por exceção Exemplo: por padrão, o nome da tabela é o mesmo da entidade, mas é configurável via metadados 23
Trabalhando com uma Entidade 24
Trabalhando com uma Entidade 25
Trabalhando com uma Entidade 26
Regras para Implementação de uma Entidade A entidade deve ser anotada com @javax.persistence.entity A anotação @javax.persistence.id deve ser usada para criar uma chave primária simples A classe entidade deve possuir um construtor sem argumentos o qual deve ser public ou protected A classe entidade não pode ser um enum ou interface, apenas class é permitido A classe entidade não deve ser final. Nenhum dos métodos ou variáveis de instância pode ser final 27
Configuração por Exceção Desde que as entidades respeitem as regras, o provedor de persistência pode fazer o mapeamento considerando algumas convenções O nome da classe é mapeado como o nome da tabela Para mudar o nome use a anotação @Table Os nomes dos atributos são mapeados como nome das colunas Para mudar o nome use a anotação @Column Para mapear os tipos de dados, as mesmas regras do JDBC são válidas Por exemplo, String mapeia para VARCHAR O tamanho do varchar tem como padrão 255 28
@Table Elementos Básicos do Mapeamento: Tabelas Pode-se definir propriedades da tabela, como seu nome Por padrão, os nomes das tabelas são criadas com letra maiúscula, assim como nome da classe Ex: @Table(name = livro") 29
Elementos Básicos do Mapeamento: Tabelas @SecondaryTable Permite que os atributos de uma Entidade (classe) possa ser distribuído entre mais de uma tabela Para várias tabelas secundárias use @SecondaryTables Exemplo: @SecondaryTables({ @SecondaryTable(name = cidade"), @SecondaryTable(name = pais") }) Para mapear os atributos para as diferentes tabelas use: @Column(table = cidade") private String cidade; Colunas que não especificarem a sua tabela serão mapeadas para a tabela primária Importante: considere questões de desempenho se optar por utilizar tabelas secundárias 30
@Id Elementos Básicos do Mapeamento: Chaves Primárias Define uma chave primária Pode ser dos seguintes tipos: Tipos primitivos: byte, int, short, long e char Classes wrapper : Byte, Integer, Short, Long, Character Strings, números e datas: String, BigInteger e Date 31
Elementos Básicos do Mapeamento: @GeneratedValue Define que a coluna ter um valor gerado automaticamente Possui quatro valores: Chaves Primárias SEQUENCE e IDENTITY: define uma coluna sequence ou identity, respectivamente. TABLE: instrui o provedor de persistência a usar uma tabela para armazenar a semente da sequencia. É criada uma tabela com duas colunas - uma contendo o nome (arbitrário) e a outra o valor AUTO: a escolha da estratégia para geração do chave é feita automaticamente Ex: @GeneratedValue(strategy = GenerationType.AUTO) 32
Elementos Básicos do Mapeamento: Atributos O JPA permite o mapeamento dos seguintes tipos: Tipos primitivos (int, double, etc.) e as classes wrapper Array de bytes e caracteres String, númerico (BigInteger) e os temporais (Date, Calendar, Time e Timestamp) Tipos enumerados e definidos pelo usuário (atributos cujo o tipo seja uma classe definida pelo desenvolvedor) Requer um mapeamento entre entidades 33
@Basic Elementos Básicos do Mapeamento: Atributos É o tipo de mapeamento mais simples, definindo (através de seus parâmetros): optional: indica se o atributo é obrigatório ou não (se pode ser null na base de dados) fetch: indica se o atributo deve ser carregado quando a aplicação utilize o valor através da chamada get (LAZY) ou se carrega-o no momento que o objeto for criado (EAGER) Exemplo: @Basic(optional=true, fetch=fetchtype.lazy) private String descricao; 34
@Column Elementos Básicos do Mapeamento: Atributos Define grande parte das propriedades comuns à colunas em banco de dados: Ex: name, length, unique etc. Algumas outras anotações: @Temporal Usada para definir datas @Transient Permite que um atributo não seja persistido Lembre-se ainda: anotações de mapeamento de atributo também podem ser usadas no método get 35
Elementos Básicos do Mapeamento: Relacionamentos (associações) No paradigma OO, as associações se resumem as seguintes formas: Unidirecional Bidirecional Com cardinalidade 36
Elementos Básicos do Mapeamento: Relacionamentos (associações) Desta forma, temos as seguintes combinações: Cardnalidade um para um um para um um para muitos um para muitos/muitos para um muitos para um muitos para muitos muitos para muitos Direcionamento Unidirecional Bidirecional Unidirecional Bidirecional Unidirecional Unidirecional Bidirecional Usaremos as seguintes notações para mapear estes relacionamentos: @OneToOne, @OneToMany, @ManyToOne, or @ManyToMany 37
Elementos Básicos do Mapeamento: Relacionamentos (associações) No paradigma OO, o direcionamento define qual classe enxerga qual Em resumo, significa qual tem um atributo de referência para qual Em um relacionamento bidirecional ambas se referem No modelo entidade-relacionamento, existe uma decisão a mais para um relacionamento bidirecional: Quem (qual tabela) fica com a informação de relacionamento (chave estrangeira)? 38
Elementos Básicos do Mapeamento: Relacionamentos (associações um para um) Mapeando um relacionamento um para um bidirecional anotações usadas: @OneToOne Indica um relacionamento um para um Só é necessária no relacionamento bidirecional para indicar quem mapeia informações de relacionamento Pode ser usado opcionalmente para definir propriedades de cascade, fetch, dentre outras @JoinColumn Elemento opcional que permite definir informações sobre a chave estrangeira (e.g., nome da coluna da chave estrageira) 39
Elementos Básicos do Mapeamento: Relacionamentos (associações um para um) 40
Elementos Básicos do Mapeamento: Relacionamentos (associações um para muitos) O relacionamento um para muitos unidirecional também pode ser mapeado por convenção Basta, para isto, que o tipo da lista seja uma @Entity Opcionalmente pode-se usar @JoinColumn para definições adicionais 41
Elementos Básicos do Mapeamento: Relacionamentos (associações um para muitos) Relacionamentos um para muitos bidirecionais são análogos ao um para um, fazendo o uso de @OneToMany (no lugar de @OneToOne) No relacionamento muitos para muitos bidirecional, como em todo relacionamento bidirecional, deve-se definir quem é o dono do relacionamento Para isto, usa-se o mappedby do @ManyToMany A tabela de mapeamento pode ser configurada com @JoinTable Esta anotação também pode ser usada no @OneToMany quando existir uma tabela de relacionamento 42
Elementos Básicos do Mapeamento: Relacionamentos (associações um para muitos) Repare que @JoinTable fica na entidade dona do relacionamento, ou seja, a que não possui um atributo mapeada por outra 43
Um pequeno parênteses: ordenando o mapeamento 44
Elementos Básicos do Mapeamento: Relacionamentos (herança) Existem três estratégias para mapeamento de herança como sempre existe uma adotada por convenção: Uma única tabela por hierarquia (SINGLE_TABLE): a soma dos atributos é distribuída em uma tabela (estratégia padrão) Joined-subclass (JOINED): nesta abordagem, cada entidade da hierarquia, concreta ou abstrata, é mapeada em uma tabela diferente Uma tabela por classe concreta (TABLE_PER_CLASS): esta estratégia mapeia cada entidade concreta para uma tabela separada 45
Elementos Básicos do Mapeamento: Relacionamentos (herança) Algumas anotações (opcionais): @Inheritance Define a estratégia de mapeamento de herança @DiscriminatorColumn Define o nome da coluna que identifica o tipo ao qual um determinado registro pertence @DiscriminatorValue Define o valor para o tipo da entidade na qual a anotação é utilizada 46
Elementos Básicos do Mapeamento: Relacionamentos (herança) - Exemplo 47
Exercício (Atividade Prática) Defina Entidades JPA para o seguinte modelo: 48
Agenda Conceitos básicos do JPA Mapeamento objeto relacional utilizando JPA Utilizando JPA para a persistência na prática EntityManager JPQL (Java Persistence Query Language) 49
Utilizando JPA para a Persistência na Prática O elemento central da manipulação e consulta da base de dados é feita pela API da classe EntityManager Provê API para criação, remoção, busca e sincronização dos objetos com o banco de dados Além disto, permite a execução de consultas JPQL As consultas JPQL assemelham-se com a SQL, mas operam sobre objetos utilizando, por exemplo, a notação de ponto (.) dentro das consultas Exercício: verificar a documentação da API da classe EntityManager http://docs.oracle.com/javaee/7/api/javax/persistence/entitymanager.html 50
Executando uma Consulta Simples Buscando pela chave primária @PersistenceContext Private EntityManager em; Book book = em.find(book.class, id); Note que o código acima não possui nenhuma referência a SQL, JPQL ou JDBC A classe EntityManager faz tudo isto por debaixo dos panos 51
Obtendo um EntityManager Existem duas formas de se obter e manipular um EntityManager Gerenciado pela Aplicação A aplicação obtém o EntityManager por meio de uma factory e também é responsável por gerenciar as transações e recursos (begin(), commit(), close() etc). Gerenciado pelo Container Em um ambiente gerenciado pelo container é possível fazer com que o EntityManager seja injetado em um EJB, por exemplo. 52
Exemplo: Persistindo uma Entidade com um EntityManager Gerenciado pelo Container @Stateless public class LivroBean { @PersistenceContext private EntityManager em; public void crialivro() { Livro livro = new Livro(); livro.settitulo("o Guia do Mochileiro das Galáxias"); livro.setpreco(38.5f); livro.setdescricao("humor e ficção científica"); livro.setnumpaginas(380); em.persist(livro); } Como pode ser visto no exemplo acima, em um ambiente gerenciado, o EntityManager não precisa ser instanciado nem ter os seus recursos e transação manipulados 53
O Contexto de Persistência Independentemente se o EntityManager é gerenciado pelo container ou pela aplicação, ele sempre está atrelado a um contexto de persistência. O contexto de persistência pode ser entendido como um cache. Toda entidade manipulada pelo EntityManager estará neste contexto evitando chamadas desnecessárias ao banco de dados. Exemplos: Quando uma entidade é recuperada através da chave primária com o método find(), o EntityManager primeiro verifica se aquele objeto já não está naquele contexto Quando o método persist() é invocado o EntityManager coloca a entidade persistida no contexto de persistência 54
O Contexto de Persistência Todo EntityManager esta ligado a uma unidade de persistência definida no arquivo persistence.xml pelo elemento <persistence-unit/> Neste elemento são definidas todas as classes que podem fazer parte de um contexto de persistência Além disto, define como as transações são manipuladas transaction-type="resource_local " para EntityManager gerenciados pela aplicação transaction-type= JTA" para EntityManagers gerenciados pelo container O escopo do contexto de persistência depende do tipo da transação utilizada pelo EntityManager, ou seja, como é gerenciado: Gerenciado pela aplicação Mantém-se enquanto o método close() do EntityManager não for chamado Gerenciado pelo container Mantém-se enquanto a transação JTA for mantida. O que normalmente significa enquanto o EJB for mantido pelo container 55
EntityManager: Buscando pelo ID Existem duas formas de buscar pelo ID Com o find() Livro livro = em.find(livro.class, 123L); if(livro!= null) { //processa o objeto } Com getreference() try { Livro livro = em.getreference(livro.class, 123L); //processa o objeto } catch (EntityNotFoundException e) { //Entidade não encontrada } Além das diferenças visíveis na forma de recuperar uma entidade, o objeto retornado por getreference() tem suas propriedades recuperadas tardiamente (lazy fetched) Dica: se for apenas fazer set no objeto, use getreference() 56
EntityManager: Removendo uma Entidade Usa-se o método remove et.begin(); em.remove(livro); et.commit(); Mas como lidar com os objetos órfãos? O JPA oferece um recurso para relacionamentos @OneToOne ou @OneToMany, desde que a entidade órfão (Capa) seja referenciada por apenas uma entidade (Livro) @OneToOne(orphanRemoval=true) private Capa capa; 57
EntityManager: Atualizando uma Entidade Gerenciada Para atualizar uma entidade gerenciada basta chamar o método persist() et.begin(); em.persist(livro); et.commit(); livro.settitulo( Novo Título ) et.begin(); em.persist(livro); et.commit(); 58
EntityManager: Cascateando Eventos Por padrão, os métodos persist() e remove() trabalham apenas com a entidade passada como parâmetro Para fazer com que as entidades relacionadas também sejam persistidas ou removidas é necessário fazer os eventos em cascata et.begin(); em.persist(livro); em.persist(capa); et.commit(); Para que capa seja persistida junto com livro sem a necessidade de persistí-los individualmente o cascade por ser usado É uma opção disponível nas diferentes anotações de relacionamento: @OneToOne, @OneToMany, @ManyToOne e @ManyToMany @OneToOne (cascade = {CascadeType.PERSIST, CascadeType.REMOVE}) private Capa capa; O código ficaria desta forma: et.begin(); em.persist(livro); et.commit(); 59
O Ciclo de Vida das Entidades em Detalhe 60
Callbacks 61
Agenda Conceitos básicos do JPA Mapeamento objeto relacional utilizando JPA Utilizando JPA para a persistência na prática EntityManager JPQL (Java Persistence Query Language) 62
JPQL: Java Persistence Query Language JPQL é uma linguagem de consulta a entidades, independente da implementação de banco de dados usada É uma linguagem fortemente baseada no SQL, mas tem sintaxe mais próxima da orientação a objetos Notação minhaclasse.meuatributo Para executar uma consulta JPQL, o JPA a transforma em SQL e realiza chamadas JDBC ao banco de dados Exemplo de uma consulta simples: SELECT l FROM Livro l WHERE l.titulo = Guia do Mochileiro das Galáxias 63
A Sintaxe do Comando SELECT Como quase todos os comandos JPQL a sintaxe do comando SELECT é idêntica ao SQL SELECT <select expression> FROM <from clause> [WHERE <conditional expression>] [ORDER BY <order by clause>] [GROUP BY <group by clause>] [HAVING <having clause>] 64
INSERT, UPDATE e DELETE O JPQL não possui o comando INSERT Os comandos UPDATE e DELETE devem ser usados apenas para atualizações em lote Exemplos: DELETE FROM Livro l WHERE l.preco < 10 UPDATE Livro l SET l.descricao = PROMOÇÃO WHERE l.preco < 10 65
Consultas Como integrar as consultas vistas anteriormente a sua aplicação? O JPA oferece 3 tipos de consultas que podem ser usadas no código Dynamic queries: é o formato mais simples de consulta, consistindo de uma consulta JPQL definida em tempo de execução Named queries: são estáticas e imutáveis Native queries: útil para executar consultas SQL nativas no lugar de JPQL 66
Consultas O EntityManager é a classe responsável por fornecer consultas (classes do tipo Query) Método Descrição Query createquery(string jpqlstring) Query createnamedquery(string name) Query createnativequery(string sqlstring, Class resultclass) Cria uma instância de Query para executar consultas dinâmicas Cria uma instância de Query para executar uma consulta nomeada Cria uma instância de Query para executar uma consulta SQL nativa passando a classe com os resultados resperados 67
A API da classe Query Os métodos mais usados são para executar uma query, podendo ser de três tipos Queries do tipo SELECT O método getresultlist() executa a consulta e retorna uma lista de resultados O método getsingleresult() executa a consulta e retorna um resultado único Para queries do tipo UPDATE e DELETE utiliza-se o método executeupdate() 68
Consultas Dinâmicas String jpqlquery = "SELECT l FROM Livro l"; if (algumcriterio) jpqlquery += " where l.preco < :pco"; query = em.createquery(jpqlquery); query.setparameter("pco", 10.0); List<Livro> livros = query.getresultlist(); É importante observar que consultas JPQL são traduzidas, em tempo de execução, para SQL usando metadados do mapeamento ORM. Isto pode ser alvo de problemas de desempenho, que pode ser resolvido por meio do uso de consultas nomeadas (estáticas e imutáveis) 69
Consultas Nomeadas Não são flexíveis como as consultas dinâmicas, pois não podem ser montadas em tempo de execução Mas são mais eficientes, em termos de desempenho, já que são traduzidas uma vez, quando a aplicação é iniciada em vez de toda vez que a consulta é executada @Entity @NamedQueries({ @NamedQuery(name = "buscatodos", query="select l from Livro l"), @NamedQuery(name = "buscapromocao", query = "select l from Livro l where l.preco < :pco") }) public class Customer { // } 70
Consultas Nomeadas Buscando todos Query query = em.createnamedquery("buscatodos"); List<Livro> livros = query.getresultlist(); Buscando três promoções Query query = em.createnamedquery("buscapromocao"); query.setparameter("pco", 10.0); query.setmaxresults(3); List<Livro> livros = query.getresultlist(); P.S: O nome da consulta deve ser único (independente da entidade que a contém) 71
Consultas Nativas Consultas nativas podem ser dinâmicas Query query = em.createnativequery("select * FROM t_livro", Livro.class); List<Livro> livros = query.getresultlist(); Ou nomeadas (estáticas) @Entity @NamedNativeQuery(name = buscatodos", query="select * from t_livro") @Table(name = "t_livro") public class Livro { // } 72
Agenda Conceitos básicos do JPA Mapeamento objeto relacional utilizando JPA Utilizando JPA para a persistência na prática EntityManager JPQL (Java Persistence Query Language) 73
Exercícios Injetar um EntityManager no EJB com agendamento criado em exercício anterior e fazer com que ele periodicamente: Crie e persista uma entidade Tempo (bastam dois campos na Tabela, id e tempoatual). Estender seu próprio projeto, transformando seus objetos de domínio em entidades persistentes JPA. 74
Exemplo Injetando um EntityManager em um EJB com agendamento para persistir informações de Livros e Autores (@ManyToMany): Três Métodos PersisteLivro Executa de 10 em 10 segundos e sorteia um livro a ser persistido. ListaLivros Executa de de 30 em 30 segundos e lista todos os livros cadastrados no banco de dados. ApagaLivro Executa de 20 em 20 segundos, sorteia um dos livros cadastrados no banco e o apaga. 75
Estrutura Alvo 76
Criando o Banco de Dados 77
Criando as Classes de Entidade (JPA) 78
@Entity @NamedQueries({ @NamedQuery(name = "findallbooks", query = "select b from Book b"), @NamedQuery(name = "findbooksbygenre", query = "select b from Book b where b.genre = :genre") }) public class Book implements Serializable { @Id @GeneratedValue(strategy = GenerationType.AUTO) private int id; // @Column(unique=true, nullable=false) private String isbn; private String title; @ManyToMany (cascade = {CascadeType.PERSIST, CascadeType.REMOVE}) private List<Author> authors; private String genre; @Temporal(TemporalType.TIMESTAMP) // opções DATE, TIME e TIMESTAMP private Date creationdate; public Book() { } public Book(String isbn, String title, List<Author> authors, String genre) { this.isbn = isbn; this.title = title; this.authors = authors; this.genre = genre; this.creationdate = new Date(); } } // getters e setters 79
@Entity public class Author implements Serializable{ @Id @GeneratedValue(strategy = GenerationType.AUTO) private int id; private String firstname; private String lastname; public Author() { } public Author(String firstname, String lastname) { this.firstname = firstname; this.lastname = lastname; } } public String getcitationstring(){ return lastname + ", " + firstname; } 80
O persistence.xml <?xml version="1.0" encoding="utf-8"?> <persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/xmlschem xsi:schemalocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"> <persistence-unit name="enterpriseapplicationexemplopersistencia-ejbpu" transaction-type="jta"> <jta-data-source>biblioteca</jta-data-source> <exclude-unlisted-classes>false</exclude-unlisted-classes> <properties> <property name="javax.persistence.schema-generation.database.action" value="create-or-extend-tables"/> </properties> </persistence-unit> </persistence> 81
O glassfish-resources.xml <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE resources PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Resource Definitions//EN" "http://glassfish.org/dtds/glassfish-resources_1_5.dtd"> <resources> <jdbc-connection-pool... name="derby_net_biblioteca_pool...> <property name="servername" value="localhost"/> <property name="portnumber" value="1527"/> <property name="databasename" value="biblioteca"/> <property name="user" value="root"/> <property name="password" value="root"/> <property name="url" value="jdbc:derby://localhost:1527/biblioteca"/> <property name="driverclass" value="org.apache.derby.jdbc.clientdriver"/> </jdbc-connection-pool> <jdbc-resource enabled="true" jndi-name="biblioteca" object-type="user" pool-name="derby_net_biblioteca_pool"/> </resources> 82
Criando o TimerSessionBean 83
Criando o TimerSessionBean @Stateless @LocalBean public class TimerBookManager { @PersistenceContext private EntityManager em; Injeção do EntityManager // Aqui entram os três métodos } 84
Método que executa de 10 em 10 segundos e sorteia um livro a ser persistido. @Schedule(dayOfWeek = "Mon-Fri", month = "*", hour = "9-22", dayofmonth = "*", year = "*", minute = "*", second = "*/10") public void persistelivro() { List<Book> books = new ArrayList(); // Criando um livro e adicionando na lista de livros List<Author> authors = new ArrayList(); Author author = new Author ("Guilherme", "Travassos"); authors.add(author); author = new Author ("Marcos", "Kalinowski"); authors.add(author); Book b = new Book("978-85-99334-75-1", "imps 2013 : evidências sobre o desempenho das empresas que adotaram o modelo MPS-SW", authors, "Científico"); books.add(b); // Mais exemplos de livros... //Sorteando o livro que será adicionado no banco Random rn = new Random(); int chosenbook = Math.abs(rn.nextInt())%books.size(); } b = books.get(chosenbook); System.out.println("Adicionando um livro " + b.tostring()); em.persist(b); 85
Método que executa de de 30 em 30 segundos e lista todos os livros cadastrados no banco de dados. @Schedule(dayOfWeek = "Mon-Fri", month = "*", hour = "9-22", dayofmonth = "*", year = "*", minute = "*", second = "*/30") public void listalivros() { //Pegando todos os livros do banco Query query = em.createnamedquery("findallbooks"); List<Book> books = query.getresultlist(); } //Listagem dos livros System.out.println("Listagem dos livros técnicos cadastrados no Banco: "); for (Book book: books){ System.out.println(book.toString()); } 86
Método que executa de 20 em 20 segundos, sorteia um dos livros cadastrados no banco e o apaga. @Schedule(dayOfWeek = "Mon-Fri", month = "*", hour = "9-22", dayofmonth = "*", year = "*", minute = "*", second = "*/20") public void apagalivro() { //Pegando todos os livros do banco Query query = em.createnamedquery("findallbooks"); List<Book> books = query.getresultlist(); //Escolhendo um livro aleatorio Random rn = new Random(); int chosenbook = Math.abs(rn.nextInt())%books.size(); Book book = books.get(chosenbook); } //Removendo ele do banco System.out.println("Removendo um livro " + book.tostring()); em.remove((book) books.get(chosenbook)); 87
Rodando o Exemplo 88
Rodando o Exemplo Saída Esperada: 89
Banco de dados e registros criados: Rodando o Exemplo 90
Leituras Sugeridas Java EE 7 Tutorial, Eric Jendrock, Ricardo Cervera-Navarro, Ian Evans, Kim Haase, William Markito Part VIII Persistence Java EE 7: The Big Picture, Danny Coward Capítulo 12, Modern Memories: The Java Persistence API 91
JPA (Java Persistence API) (kalinowski@ic.uff.br)