A BD ORACLE, cuja criação foi tratada em "Exemplo de Aplicação Java Swing com BD Oracle - 1", usa sequências e triggers para atribuição automática da chave em cada tabela.
O JPA permite-nos fazer operações sobre a BD (criar, alterar, apagar ou selecionar registos das tabelas). No entanto, quando queremos fazer várias operações relacionadas, e precisamos de saber que chave foi atribuída pela BD a um dado registo criado anteriormente, cujo objeto ainda temos em memória, não temos maneira segura de conhecer o valor dessa chave. E, o objeto que ainda temos em memória permanece sem o valor da chave nos seus atributos, fazendo com que o JPA considere que essa instância não é gerida por si. Isto, impede-nos de usar essa instância para operações subsequentes com a BD.
O ORACLE, tipicamente usa sequências para atribuição de valores de chave primária nas suas tabelas.
A utilização dessas sequências na atribuição da chave primária pode fazer-se definindo um default value para a coluna respetiva, ou criando um trigger before insert o qual obtém o valor seguinte da sequência e o atribui à coluna da chave primária da tabela.
Qualquer Entidade JPA (classe associada a uma tabela) deve ter uma chave primária. Para fazer o JPA atualizar o valor da chave na instância da Entidade, quando essa instância é persistida (armazenada) na BD, precisamos de deixar que seja o JPA a gerir a atribuição dos valores a essas chaves.
Assim, temos várias hipóteses de configuração da Entidade JPA:
- Campo de chave primária simples: Utiliza @Id
- Campo de chave primária gerado automaticamente: Utiliza @Id e @GeneratedValue. Aqui temos, pelo menos, duas alternativas:
- Gerar ID a partir de uma tabela
- Gerar ID a partir de uma sequência
Vamos aqui usar a alternativa de geração do ID a partir de uma sequência.
Ao gerar as entidades JPA a partir da BD ORACLE, no artigo anterior, para cada chave primária foi gerada a seguinte anotação de chave primária simples:
@Id
@Basic(optional = false)
@Column(nullable = false)
private Integer bookid;
(exemplo na Entidade Book, associada à tabela BOOK)
Neste caso, o JPA não gera nem faz a gestão das chaves primárias, não atualizando o atributo chave nas instâncias de entidades JPA que persista na BD.
Para deixar ser o JPA a gerir e gerar as chaves primárias a partir de uma sequência criada na BD ORACLE, precisamos de eliminar o trigger que atribui a chave, e colocar as seguintes anotações JPA em substituição das anteriores:
@SequenceGenerator(
name="BOOK_SEQUENCE_GENERATOR",
sequenceName="BOOK_SEQ",
allocationSize=25
)
@Id
@GeneratedValue(strategy=SEQUENCE, generator="BOOK_SEQUENCE_GENERATOR")
@Column(name="BOOKID", nullable = false)
private Integer bookid;
O que fizemos foi:
1º - Usando @SequenceGenerator definir um Generator de chaves a partir da sequência identificada (neste caso BOOK_SEQ);
2º - Usando @Id @GeneratedValue dizer ao JPA que a chave deve ser gerada usando o SequenceGenerator definido acima.
Após fazer esta alteração em BOOK e uma alteração similar em AUTHOR, passa a ser possível fazer algo como o seguinte, no exemplo do artigo anterior:
em.getTransaction().begin();
Author au = new Author();
au.setName("Sousa");
au.setSurname("Tavares");
em.persist(au);
//imprimir o valor da PK criada na BD
System.out.println(au.getIdauthor());
Book nbook = new Book();
nbook.setTitle("Equador");
nbook.setIsbn("12345");
nbook.setEdition(3);
nbook.setAuthorSet( new HashSet<>()); nbook.getAuthorSet().add(au);
em.persist(nbook);
em.getTransaction().commit();
Este excerto de código irá criar um autor na tabela AUTHOR, um livro na tabela BOOK, e um registo associando o autor ao livro em BOOKAUTHOR.
No próximo artigo iremos criar um projeto Java Class Library usando as entidades JPA que criámos anteriormente, a qual pretenderá fornecer funções/serviços de lógica do negócio (BLL, Business Logic Layer) para uma camada de User Interface.
Sem comentários:
Enviar um comentário