Programação Orientada A Objetos em Java t5
Programação Orientada A Objetos em Java t5
Utilização de tecnologia Java, com base no middleware JDBC, para manipulação e consulta aos
dados de bancos relacionais, com base em comandos diretos, ou por meio de mapeamento
objeto-relacional.
PROPÓSITO
Implementar os diversos processos de persistência necessários aos sistemas cadastrais, com
base em modelos robustos de programação, permitindo satisfazer a uma demanda de mercado
natural na construção de sistemas com esse perfil. Ao final dos estudos, você estará apto a
construir sistemas com acesso a bancos de dados relacionais, utilizando tecnologia Java.
PREPARAÇÃO
Antes de iniciar o conteúdo, é necessário configurar o ambiente, com a instalação do JDK e
Apache NetBeans, definindo a plataforma de desenvolvimento que será utilizada na codificação e
execução dos exemplos práticos.
OBJETIVOS
MÓDULO 1
MÓDULO 2
MÓDULO 3
INTRODUÇÃO
Neste conteúdo, analisaremos as ferramentas para acesso a banco de dados com uso das
tecnologias JDBC e JPA, pertencentes ao ambiente Java, incluindo exemplos de código para
efetuar consulta e manipulação de registros.
Após compreender os princípios funcionais das tecnologias sob análise, construiremos um sistema
cadastral simples e veremos como aproveitar os recursos de automatização do NetBeans para
construção de componentes JPA.
MÓDULO 1
MIDDLEWARE
Para definirmos middleware, devemos entender os conceitos de front-end e back-end.
FRONT-END
Quando falamos de front-end, estamos nos referindo à camada de software responsável pelo
interfaceamento do sistema, com o uso de uma linguagem de programação. Aqui, utilizaremos os
aplicativos Java como opção de front-end.
BACK-END
Já o back-end compreende o conjunto de tecnologias com a finalidade de fornecer recursos
específicos, devendo ser acessadas a partir de nosso front-end, embora não façam parte do
mesmo ambiente, como os bancos de dados e as mensagerias. Para nossos exemplos,
adotaremos o banco de dados Derby como back-end.
SAIBA MAIS
As mensagerias são outro bom exemplo de back-end, com uma arquitetura voltada para a
comunicação assíncrona entre sistemas, efetuada por meio da troca de mensagens. Essa é uma
tecnologia crucial para diversos sistemas corporativos, como os da rede bancária.
Foi definido o termo middleware para a classificação desse tipo de tecnologia, que permite
integração de forma transparente e mudança de fornecedor com pouca ou nenhuma alteração de
código.
No ambiente Java, temos o JDBC (Java Database Connectivity) como middleware para acesso
aos diferentes tipos de bancos de dados. Ele permite que utilizemos produtos de diversos
fornecedores, sem modificações no código do aplicativo, sendo a consulta e manipulação de
dados efetuadas por meio de comandos SQL (Structured Query Language) em meio ao código
Java.
ATENÇÃO
Devemos evitar a utilização de comandos para um tipo de banco de dados específico, mantendo
sempre a sintaxe padronizada pelo SQL ANSI, pois, caso contrário, a mudança do fornecedor de
back-end poderá exigir mudanças no front-end.
BANCO DE DADOS DERBY
Entre as diversas opções de repositórios existentes, temos o Derby, ou Java DB, um banco de
dados relacional construído totalmente com tecnologia Java, que não depende de um servidor e
faz parte da distribuição padrão do JDK. Apache Derby é um subprojeto do Apache DB, disponível
sob licença Apache, e que pode ser embutido em programas Java, bem como utilizado para
transações on-line.
Podemos gerenciar nossos bancos de dados Derby de forma muito simples, por meio da aba
Services do NetBeans, na divisão Databases. Para isso, devemos clicar com o botão direito
sobre o driver Java DB, escolher a opção Create Database, como ilustrado na imagem, e
preencher as informações necessárias para a configuração da nova instância do banco de dados:
Vamos agora criar um banco de dados Java DB chamado “escola”. Para isso, na janela que será
aberta, devemos preencher o nome de nosso novo banco de dados com o valor "escola", bem
como usuário e senha, onde seria interessante defini-los também como "escola", tornando mais
fácil lembrar os valores utilizados. Ao clicar no botão de confirmação, o banco de dados será
criado e ficará disponível para conexão, sendo identificado por sua Connection String, a qual é
formada a partir do endereço de rede (localhost), porta padrão (1527) e instância que será
utilizada (escola).
A conexão é aberta com o duplo clique sobre o identificador, ou o clique com o botão direito e
escolha da opção Connect. Com o banco de dados aberto, podemos criar uma tabela, navegando
até a divisão Tables, no esquema ESCOLA, e utilizando o clique com o botão direito, para
acessar a opção Create Table no menu de contexto.
Na janela que se abrirá, iremos configurar a tabela Aluno, com os campos definidos de acordo
com o quadro seguinte.
Atenção! Para visualização completa da tabela utilize a rolagem horizontal
Definindo o nome da tabela e adicionando os campos, teremos a configuração que pode ser
observada a seguir, com o processo sendo finalizado por meio do clique em OK. Cada campo
deve ser adicionado individualmente, com o clique em Add Column.
Captura de tela da ferramenta de criação visual para tabelas.
A tabela criada será acessada por meio de um novo nó, na árvore de navegação, abaixo de
Tables, com o nome Aluno. Utilizando o clique com o botão direito sobre o novo nó e escolhendo
a opção View Data, teremos a abertura de uma área para execução de SQL e visualização de
dados no editor de código, sendo possível acrescentar registros de forma visual com o uso de
ALT+I, ou clique sobre o ícone referente.
DICA
Experimente acrescentar alguns registros, na janela de inserção que será aberta com as teclas
ALT+I, utilizando Add Row para abrir novas linhas e preenchendo os valores dos campos para
cada linha.
Existem quatro tipos de drivers JDBC, os quais são apresentados no quadro seguinte:
Atenção! Para visualização completa da tabela utilize a rolagem horizontal
EXEMPLO
Se considerarmos o caso específico do Oracle, são disponibilizados um driver Tipo 2, com acesso
via OCI (Oracle Call Interface), e um driver Tipo 4, com o nome Oracle Thin Driver. A utilização
da versão thin driver é mais indicada, pois não necessita da instalação do Oracle Cliente na
máquina do usuário.
O processo para utilizar as funcionalidades básicas do JDBC segue quatro passos simples:
Por exemplo, se quisermos efetuar a inclusão de um aluno na base de dados, podemos escrever o
trecho de código apresentado a seguir, com o objetivo de demonstrar os passos descritos
anteriormente:
// passo 1
Class.forName("org.apache.derby.jdbc.ClientDriver");
// passo 2
Connection c1 = DriverManager.getConnection(
"jdbc:derby://localhost:1527/escola",
"escola", "escola");
// passo 3
Statement st = c1.createStatement();
// passo 4
st.executeUpdate(
st.close();
c1.close();
No início do código, temos a instância do driver Derby sendo gerada a partir de uma chamada
para o método forName. Com o driver na memória, podemos abrir conexões com o banco de
dados por meio do middleware JDBC.
A partir da conexão c1, é gerado um executor de SQL de nome st, com a chamada para o método
createStatement. Estando o executor instanciado, realizamos a inserção de um registro,
invocando o método executeUpdate, com o comando SQL apropriado.
Na parte final, devemos fechar os componentes JDBC, na ordem inversa daquela em que foram
criados, já que existe dependência sucessiva entre eles.
ATENÇÃO
Class.forName("org.apache.derby.jdbc.ClientDriver");
Connection c1 = DriverManager.getConnection(
"jdbc:derby://localhost:1527/loja",
"loja", "loja");
Statement st = c1.createStatement();
while(r1.next())
r1.close();
st.close();
c1.close();
Após a recepção da consulta no objeto de nome r1, podemos nos movimentar pelos registros,
com o uso de next, e acessar cada campo pelo nome, para a obtenção do valor, sempre
lembrando de utilizar o método correto para o tipo do campo, como getString, para texto, e getInt,
para valores numéricos inteiros.
Ao efetuar a consulta, o ResultSet fica posicionado antes do primeiro registro, na posição BOF
(Beginning of File), e com o uso do comando next podemos mover para as posições seguintes,
até atingir o final da consulta, na posição EOF (End of File). A cada registro visitado, efetuamos a
impressão do nome do aluno e ano de entrada.
A biblioteca JDBC deve ser adicionada ao projeto, ou ocorrerá erro durante a execução. Para o
nosso exemplo, devemos adicionar a biblioteca Java DB Driver, por meio do clique com o botão
direito na divisão Libraries e uso da opção Add Library.
Captura de tela da adição do driver Java DB ao projeto.
Class.forName("org.apache.derby.jdbc.ClientDriver");
Connection c1 = DriverManager.getConnection(
"jdbc:derby://localhost:1527/loja",
"loja", "loja");
PreparedStatement ps = c1.prepareStatement(
ps.setInt(1,2018);
ps.executeUpdate();
ps.close();
c1.close();
O uso de parâmetros facilita a escrita do comando SQL, sem a preocupação com o uso de
apóstrofe ou outro delimitador, além de representar uma proteção contra os ataques do tipo SQL
Injection.
SQL INJECTION
É um tipo de ataque a uma aplicação web, baseado na injeção e execução de instruções
SQL mal-intencionadas, que é a linguagem utilizada para troca de informações entre
aplicações e bancos de dados relacionais. O SQL Injection visa comprometer a base de
dados associada à aplicação web atacada por ele.
ATENÇÃO
Cada parâmetro deve ser preenchido com a chamada ao método correto, de acordo com seu tipo,
como setInt, para inteiro, e setString, para texto. Após o preenchimento, devemos executar o
comando SQL, com a chamada para executeUpdate, no caso das instruções INSERT, UPDATE e
DELETE, ou executeQuery, para a instrução SELECT.
No exemplo, o parâmetro foi preenchido com o valor 2018, e a execução do comando SQL
resultante irá remover da base todos os alunos com entrada no referido ano.
COMPONENTES DO JDBC
Chegamos ao fim do módulo 1! Antes de verificar o seu aprendizado, assista ao vídeo a seguir, em
que são apresentados os componentes oferecidos pelo JDBC.
VERIFICANDO O APRENDIZADO
1. COM O ADVENTO DOS BANCOS DE DADOS, TORNOU-SE COMUM A
CONSTRUÇÃO DE SISTEMAS CADASTRAIS QUE UTILIZAM ESSE TIPO DE
REPOSITÓRIO. NO ENTANTO, HÁ DIVERSOS FORNECEDORES PARA
SISTEMAS DE GERENCIAMENTO DE BANCOS DE DADOS, TORNANDO-SE
UMA BOA PRÁTICA, NA CONSTRUÇÃO DE UM SISTEMA CADASTRAL:
A) ResultSet
B) DriverManager
C) PreparedStatement
D) Connection
E) Statement
GABARITO
MÓDULO 2
ATENÇÃO
Torna-se necessário efetuar uma conversão entre os dois modelos de representação, o que é feito
com a criação de uma classe de entidade para expressar cada tabela do banco de dados, à
exceção das tabelas de relacionamento. Segundo a conversão efetuada, os atributos da classe
serão associados aos campos da tabela, e cada registro poderá ser representado por uma
instância da classe.
Para a nossa tabela de exemplo, podemos utilizar a classe apresentada a seguir, na qual, para
simplificar o código, não iremos utilizar métodos getters e setters.
public Aluno() { }
this.matricula = matricula;
this.nome = nome;
this.ano = ano;
Tendo definido a entidade, podemos mudar a forma de lidar com os dados, efetuando a leitura dos
dados da tabela e alimentando uma coleção que representará os dados para o restante do
programa.
Class.forName("org.apache.derby.jdbc.ClientDriver");
Connection c1 = DriverManager.getConnection(
"jdbc:derby://localhost:1527/loja",
"loja", "loja");
Statement st = c1.createStatement();
while(r1.next())
lista.add(new Aluno(r1.getString("MATRICULA"),
r1.getString("NOME"),
r1.getInt("ENTRADA")));
r1.close();
st.close();
c1.close();
Como podemos observar, o código apresenta grande similaridade com o trecho para consulta
apresentado anteriormente, mas aqui instanciamos uma coleção, e para cada registro obtido,
adicionamos um objeto inicializado com seus dados. Tendo concluído o preenchimento da
coleção, aqui com o nome lista, não precisamos acessar novamente a tabela e podemos lidar
com os dados segundo uma perspectiva orientada a objetos.
Se quisermos listar o conteúdo da tabela, em outro ponto do código, após alimentar a coleção de
entidades, podemos utilizar um código baseado na funcionalidade padrão das coleções do Java.
aluno.ano);
ATENÇÃO
Normalmente, temos uma classe DAO para cada classe de entidade relevante para o sistema.
Como a codificação das operações sobre o banco apresenta muitos trechos comuns para as
diversas entidades do sistema, podemos concentrar as similaridades em uma classe de base, e
derivar as demais, segundo o princípio de herança. A utilização de elementos genéricos também
será um facilitador na padronização das operações comuns sobre a tabela, como inclusão,
exclusão, alteração e consultas.
Vamos observar, no trecho de código seguinte, a definição de uma classe de base, a partir da qual
serão derivadas todas as classes DAO do sistema.
Class.forName("org.apache.derby.jdbc.ClientDriver");
return DriverManager.getConnection(
"jdbc:derby://localhost:1527/escola",
"escola", "escola");
return getConnection().createStatement();
st.getConnection().close();
COMENTÁRIO
Class.forName("oracle.jdbc.OracleDriver");
return DriverManager.getConnection(
jdbc:oracle:thin:@localhost:1521:XE",
"escola","escola");
@Override
try {
ResultSet r1 = getStatement().executeQuery(
while(r1.next())
lista.add(new Aluno(r1.getString("MATRICULA"),
r1.getString("NOME"),r1.getInt("ENTRADA")));
closeStatement(r1.getStatement());
}catch(Exception e){
}
return lista;
@Override
try {
PreparedStatement ps =
getConnection().prepareStatement(
ps.setString(1, chave);
ResultSet r1 = ps.executeQuery();
if (r1.next())
r1.getString("NOME"),
r1.getInt("ENTRADA"));
closeStatement(ps);
} catch (Exception e) {
return aluno;
COMENTÁRIO
O código ainda não está completo, e certamente apresentará erro, devido ao fato de que não
implementamos todos os métodos abstratos definidos, mas já temos o método obterTodos
codificado neste ponto. Ele irá retornar todos os registros de nossa tabela, no formato de um
ArrayList de entidades do tipo Aluno, sendo inicialmente executado o SQL necessário para a
consulta e, em seguida, adicionada uma entidade à lista para cada registro obtido no cursor.
Também podemos observar o método obter, para consulta individual, retornando uma entidade do
tipo Aluno para uma chave fornecida do tipo String. A implementação do método envolve a
execução de uma consulta parametrizada, em que o campo matrícula deve coincidir com o valor
da chave, sendo retornado o registro equivalente por meio de uma instância de Aluno.
Note que, como a consulta foi efetuada a partir da chave, sempre retornará um registro ou
nenhum, sendo necessário apenas o comando if para mover do BOF para o primeiro e único
registro. Caso a chave não seja encontrada, a rotina não entrará nessa estrutura condicional e
retornará um produto nulo.
Agora que a consulta aos registros foi implementada, devemos acrescentar os métodos de
manipulação de dados na classe AlunoDAO.
@Override
try {
PreparedStatement ps = getConnection().prepareStatement(
ps.setString(1, entidade.matricula);
ps.setString(2, entidade.nome);
ps.setInt(3, entidade.ano);
ps.executeUpdate();
closeStatement(ps);
} catch (Exception e) { }
@Override
try {
PreparedStatement ps = getConnection().prepareStatement(
ps.setString(1, chave);
ps.executeUpdate();
closeStatement(ps);
} catch (Exception e) { }
@Override
try {
PreparedStatement ps = getConnection().prepareStatement(
ps.setString(1, entidade.nome);
ps.setInt(2, entidade.ano);
ps.setString(3, entidade.matricula);
ps.executeUpdate();
closeStatement(ps);
} catch (Exception e) { }
O mais simples dos métodos implementados se refere ao excluir, por necessitar apenas da chave
primária e uso da instrução DELETE condicionada à chave fornecida. Os demais métodos seguem
a mesma forma de implementação, com a obtenção dos valores para preenchimento dos
parâmetros a partir dos atributos da entidade fornecida, sendo o método incluir relacionado ao
comando INSERT, e o método alterar representando as instruções SQL do tipo UPDATE.
ATENÇÃO
Uma regra para efetuar mapeamento objeto-relacional, e que é seguida por qualquer framework
com esse objetivo, é a de que a chave primária da tabela não pode ser alterada. Isso permite
manter o referencial dos registros ao longo do tempo.
Após construir a classe DAO, podemos utilizá-la ao longo de todo o sistema, consultando e
manipulando os dados sem a necessidade de utilização direta de comandos SQL, como pode ser
observado no trecho de exemplo apresentado a seguir, que permitiria imprimir o nome de todos os
alunos da base de dados.
dao.obterTodos().forEach(aluno -> {
System.out.println(aluno.nome);
});
PADRÃO DAO
Assista ao vídeo a seguir e veja um resumo sobre o padrão de desenvolvimento DAO. Além disso,
veja como ele pode ser implementado em ambiente Java.
Tomando como exemplo nossa tabela de alunos, a entidade Java receberia as anotações
observadas no fragmento de código seguinte, para que seja feito o mapeamento com base no
JPA.
@Entity
@Table(name = "ALUNO")
@NamedQueries({
@NamedQuery(name = "Aluno.findAll",
@Id
@Basic(optional = false)
@Column(name = "MATRICULA")
@Column(name = "NOME")
@Column(name = "ENTRADA")
public Aluno() {
this.matricula = matricula;
As anotações utilizadas são bastante intuitivas, como Entity transformando a classe em uma
entidade, Table selecionando a tabela na qual os dados serão escritos, e Column associando o
atributo a um campo da tabela. As características específicas dos campos podem ser mapeadas
por meio de anotações como Id, que determina a chave primária, e Basic, na qual o parâmetro
optional permite definir a obrigatoriedade ou não do campo.
Também é possível definir consultas em sintaxe JPQL, uma linguagem de consulta do JPA que
retorna objetos, ao invés de registros. As consultas em JPQL podem ser criadas em meio ao
código do aplicativo, ou associadas à classe com anotações NamedQuery.
Toda a configuração da conexão com banco é efetuada em um arquivo no formato XML com o
nome persistence. No mesmo arquivo deve ser escolhido o driver de persistência.
xsi:schemaLocation="">
<persistence-unit name="ExemploJavaDB01PU"
transaction-type="RESOURCE_LOCAL">
<provider>
org.eclipse.persistence.jpa.PersistenceProvider
</provider>
<class>modelJPA.Aluno</class>
<properties>
<property name="javax.persistence.jdbc.url"
value="jdbc:derby://localhost:1527/escola"/>
<property name="javax.persistence.jdbc.user"
value="escola"/>
<property name="javax.persistence.jdbc.driver"
value="org.apache.derby.jdbc.ClientDriver"/>
<property name="javax.persistence.jdbc.password"
value="escola"/>
</properties>
</persistence-unit>
</persistence>
Analisando o arquivo persistence do exemplo, temos uma unidade de persistência com o nome
ExemploJavaDB01PU, sendo a conexão com o banco de dados definida por meio das
propriedades url, user, driver e password, com valores equivalentes aos que são adotados na
utilização padrão do JDBC. Também temos a escolha das entidades que serão incluídas no
esquema de persistência, no caso apenas Aluno, e do provedor de persistência, em que foi
escolhido Eclipse Link, mas que poderia ser trocado por Hibernate ou Oracle Top Link, entre
outras opções.
Com os elementos do projeto devidamente configurados, poderíamos utilizá-los para listar o nome
dos alunos, por meio do fragmento de código apresentado a seguir.
EntityManagerFactory emf =
Persistence.createEntityManagerFactory("ExemploJavaDB01PU");
EntityManager em = emf.createEntityManager();
lista.forEach(aluno->{
System.out.println(aluno.getNome());
});
Observe como o uso de JPA diminui muito a necessidade de programação nas tarefas
relacionadas ao mapeamento objeto-relacional. Tudo que precisamos fazer é instanciar um
EntityManager a partir da unidade de persistência, recuperar o objeto Query e, a partir dele,
efetuar a consulta por meio do método getResultList, o qual já retorna uma lista de entidades,
sem a necessidade de programar o preenchimento dos atributos.
VERIFICANDO O APRENDIZADO
1. O USO DE COMANDOS SQL DISPERSOS, EM MEIO AO CÓDIGO DO
APLICATIVO, DIMINUI O REUSO E AUMENTA A DIFICULDADE DE
MANUTENÇÃO. COM BASE NO PADRÃO DE DESENVOLVIMENTO DAO,
TEMOS A CONCENTRAÇÃO DOS COMANDOS SQL EM UMA ÚNICA
CLASSE, EM QUE EXISTEM MÉTODOS PARA O RETORNO DE ENTIDADES,
COMO OBTERTODOS, QUE ESTÃO RELACIONADOS AO COMANDO:
A) INSERT
B) CREATE
C) DELETE
D) UPDATE
E) SELECT
A) EntityManager
B) Query
C) Transaction
D) EntityManagerFactory
E) Persistence
GABARITO
1. O uso de comandos SQL dispersos, em meio ao código do aplicativo, diminui o reuso e
aumenta a dificuldade de manutenção. Com base no padrão de desenvolvimento DAO,
temos a concentração dos comandos SQL em uma única classe, em que existem métodos
para o retorno de entidades, como obterTodos, que estão relacionados ao comando:
Na construção de uma classe DAO, precisamos minimamente dos métodos obterTodos, incluir,
excluir e alterar, que estarão relacionados, respectivamente, aos comandos SELECT, INSERT,
DELETE e UPDATE. Com base nesses métodos, temos a possibilidade de listar os registros,
acrescentar um novo registro, alterar os dados do registro ou, ainda, remover um registro da base
de dados.
MÓDULO 3
Vamos criar uma classe com o nome SistemaEscola, sendo apresentada, a seguir, sua
codificação inicial, incluindo a definição da instância de AlunoDAO e os métodos para exibição
de valores, tanto para um aluno quanto para o conjunto completo deles.
new BufferedReader(
new InputStreamReader(System.in));
System.out.println("Aluno: "+aluno.nome+
"\nMatricula: "+aluno.matricula+
"\tEntrada: "+aluno.ano+
"\n==========================");
dao.obterTodos().forEach(aluno->exibir(aluno));
COMENTÁRIO
Note como o método exibirTodos utiliza notação lambda para percorrer toda a coleção de alunos,
com chamadas sucessivas para o método exibir, o qual recebe uma instância de Aluno e imprime
seus dados no console.
Também temos uma instância estática de BufferedReader encapsulando o teclado, com o nome
entrada, que será utilizada para receber as respostas do usuário nos demais métodos da classe.
Vamos verificar sua utilização nos métodos apresentados a seguir, que deverão ser adicionados
ao código de SistemaEscola.
System.out.println("Nome:");
aluno.nome = entrada.readLine();
System.out.println("Matricula:");
aluno.matricula = entrada.readLine();
System.out.println("Entrada:");
aluno.ano = Integer.parseInt(entrada.readLine());
dao.incluir(aluno);
System.out.println("Matricula:");
dao.excluir(matricula);
Para finalizar nosso sistema cadastral, precisamos adicionar à classe um método main, conforme
o trecho de código apresentado a seguir.
while(true){
System.out.println(
"1-Listar\t2-Inserir\t3-Excluir\t0-Sair");
if(opcao==0)
break;
switch(opcao){
case 1:
sistema.exibirTodos();
break;
case 2:
sistema.inserirAluno();
break;
case 3:
sistema.excluirAluno();
break;
O método main permite executar o exemplo, que na prática é bem simples, oferecendo as opções
de listagem, inclusão, exclusão e término, a partir da digitação do número correto pelo usuário.
Feita a escolha da opção, foi necessário apenas ativar o método correto da classe, dentre aqueles
que acabamos de codificar.
Com tudo pronto, podemos utilizar as opções Build e Run File do NetBeans, causando a
execução pelo painel Output, como pode ser observado a seguir:
SAIBA MAIS
Com o uso de transações, temos a garantia de que o banco irá desfazer as operações anteriores
à ocorrência de um erro, como na inclusão dos itens de uma nota fiscal. Sem o uso de uma
transação, caso ocorresse um erro na inclusão de algum item, seríamos obrigados a desfazer as
inclusões que ocorreram antes do erro, de forma programática, mas com a transação será
necessário apenas emitir um comando de rollback.
A inclusão de transações em nosso sistema seria algo bastante simples, pois bastaria efetuar
modificações pontuais na classe AlunoDAO. Podemos observar um dos métodos modificados a
seguir.
@Override
Connection c1 = null;
try {
c1 = getConnection();
c1.setAutoCommit(false);
PreparedStatement ps = getConnection().prepareStatement(
ps.setString(1, chave);
ps.executeUpdate();
c1.commit();
closeStatement(ps);
} catch (Exception e) {
if(c1!=null)
try {
c1.rollback();
c1.close();
Aqui temos a modificação do método excluir para utilizar transações, o que exige que a conexão
seja modificada.
Por padrão, cada alteração é confirmada automaticamente, mas utilizando setAutoCommit com
valor false, a sequência de operações efetuadas deve ser confirmada com o uso de commit.
Podemos observar, no código, que após desligar a confirmação automática, temos o mesmo
processo utilizado antes para geração e execução do SQL parametrizado, mas com a diferença do
uso de commit antes de closeStatement. Caso ocorra um erro, será acionado o bloco catch,
com a chamada para rollback e o fechamento da conexão.
A forma de lidar com transações no JPA segue um processo muito similar, como pode ser
observado no trecho de código a seguir.
createEntityManagerFactory("ExemploJavaDB01PU");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
try {
em.persist(aluno);
em.getTransaction().commit();
} catch (Exception e) {
em.getTransaction().rollback();
} finally {
em.close();
}
Como já era esperado, o uso de JPA permite um código muito mais simples, embora os princípios
relacionados ao controle transacional sejam similares. O controle deve ser obtido com
getTransaction, a partir do qual uma transação é iniciada com begin, sendo confirmada com o
uso de commit, ou cancelada com rollback.
Acionar o menu New File, escolhendo a opção Entity Classes from Database.
Selecionar a conexão JDBC correta (escola).
Adicionar as tabelas de interesse, o que no caso seria apenas Aluno.
Escrever o nome do pacote (model) e deixar marcada apenas a opção de criação para a unidade
de persistência.
Definir o tipo de coleção como List.
Acionar o menu New File, escolhendo a opção Entity Classes from Database.
Escrever o nome do pacote (model) e deixar marcada apenas a opção de criação para a unidade
de persistência.
Após a conclusão do procedimento, teremos a criação da entidade Aluno, no pacote model, com
a codificação equivalente à que foi apresentada no módulo 2, abordando o JPA, bem como o
arquivo persistence, em META-INF.
Com nossa entidade gerada, podemos gerar um DAO de forma automatizada, por meio dos
seguintes passos:
Acionar o menu New File, escolhendo JPA Controller Classes for Entity Classes.
Selecionar as entidades, o que no caso seria apenas Aluno.
Escrever o nome do pacote (manager).
Novamente, é possível observar os passos descritos por meio de uma sequência de imagens
capturadas da tela do gerador automático de entidades JPA:
Acionar o menu New File, escolhendo JPA Controller Classes for Entity Classes.
Capturadas da tela do gerador automático de entidades JPA
Ao término do processo, teremos um pacote com exceções customizadas, e outro com a classe
DAO, com o nome AlunoJpaController, onde temos todas as operações básicas sobre a tabela
Aluno, utilizando tecnologia JPA.
Todas as operações para manipulação de dados são feitas a partir do EntityManager, em que os
métodos adequados podem ser observados no quadro apresentado a seguir:
Atenção! Para visualização completa da tabela utilize a rolagem horizontal
EntityManager em = null;
try {
em = getEntityManager();
em.getTransaction().begin();
Aluno aluno;
try {
aluno.getMatricula();
em.remove(aluno);
em.getTransaction().commit();
} finally {
if (em != null)
em.close();
Após utilizar os recursos de automatização do NetBeans, podemos criar uma classe Java com o
nome SistemaEscola, muito similar à que foi gerada anteriormente, mas com as modificações
necessárias para uso do JPA.
Persistence.createEntityManagerFactory(
"ExemploEntidadeJPAPU"));
System.out.println("Aluno: "+aluno.getNome()+
"\nMatricula: "+aluno.getMatricula()+
"\tEntrada: "+aluno.getEntrada()+
"\n==========================");
dao.findAlunoEntities().forEach(aluno->exibir(aluno));
System.out.println("Nome:");
aluno.setNome(entrada.readLine());
System.out.println("Matricula:");
aluno.setMatricula(entrada.readLine());
System.out.println("Entrada:");
aluno.setEntrada(Integer.parseInt(entrada.readLine()));
dao.create(aluno);
System.out.println("Matricula:");
dao.destroy(matricula);
while(true){
System.out.println(
"1-Listar\t2-Inserir\t3-Excluir\t0-Sair");
if(opcao==0)
break;
switch(opcao){
ATENÇÃO
Enquanto as bibliotecas JPA são adicionadas de forma automática no projeto, teremos de
adicionar manualmente a biblioteca Java DB Driver, conforme processo já descrito. Após
adicionar a biblioteca, podemos executar o projeto, obtendo o mesmo comportamento do exemplo
criado anteriormente, com uso de DAO.
AUTOMATIZAÇÕES DO NETBEANS
Estamos concluindo o módulo 3! Agora, assista ao vídeo a seguir para obter uma descrição das
funcionalidades do NetBeans para geração de entidades a partir do banco de dados, bem como
controladores JPA a partir das entidades, e demonstração do uso do ferramental na construção
rápida de aplicativos cadastrais.
VERIFICANDO O APRENDIZADO
A) Transaction
B) Connection
C) EntityManager
D) Query
E) ResultSet
GABARITO
1. Por meio do controle transacional, é possível gerenciar blocos de operações como uma
ação única, que pode ser desfeita pelo banco de dados sem maiores esforços em termos de
programação. Em termos de JDBC padrão, qual classe é responsável pela transação?
No uso do JDBC padrão, temos a gerência de conexões por meio de Connection. Iniciada com o
desligamento do commit automático, a transação deve ser confirmada por meio do método commit
de Connection, enquanto o uso de rollback desfaz as operações.
2. Ferramentas de produtividade sempre devem ser observadas, pois nos permitem eliminar
tarefas repetitivas e obter maior resultado em menor tempo. Com o NetBeans é possível
gerar as entidades JPA a partir de um banco de dados já constituído, sendo necessário
apenas:
Utilizando o NetBeans, temos a opção de criação "Entity Classes from Database", em que
podemos selecionar as tabelas de determinada conexão e deixar que a IDE gere todo o código
necessário para as entidades. Tudo que precisamos, para recuperar as tabelas, é conhecer a
conexão JDBC com o banco de dados.
CONCLUSÃO
CONSIDERAÇÕES FINAIS
Analisamos neste conteúdo duas tecnologias para acesso e manipulação de dados no ambiente
Java, que são JDBC e JPA, em que o primeiro é o middleware de acesso a bancos de dados do
Java, e o segundo uma arquitetura de persistência baseada em anotações.
Vimos que é possível trabalhar apenas com JDBC, utilizando os componentes ao longo do código,
mas a propagação de comandos SQL ao longo dos códigos nos levou à adoção do padrão DAO,
organizando nossos códigos e trazendo o nível de padronização exigido para o surgimento de
ferramentas como o JPA.
AVALIAÇÃO DO TEMA:
REFERÊNCIAS
CORNELL, G.; HORSTMANN, C. Core Java. 8. ed. São Paulo: Pearson, 2010.
DEITEL, P.; DEITEL, H. Ajax, Rich Internet Applications e Desenvolvimento Web para
Programadores. São Paulo: Pearson Education, 2009.
DEITEL, P.; DEITEL, H. Java, Como Programar. 8. ed. São Paulo: Pearson, 2010.
MONSON-HAEFEL, R.; BURKE, B. Enterprise Java Beans 3.0.5. USA: O’Reilly, 2006.
EXPLORE+
Para saber mais sobre os assuntos tratados neste conteúdo, leia:
CONTEUDISTA
Denis Gonçalves Cople
CURRÍCULO LATTES