Você está na página 1de 16

Exemplo de Aplicao Java Swing com BD Oracle - 1

Hoje vamos iniciar uma srie de artigos que culminaro com uma pequena aplicao exemplo de
gesto de biblioteca, feita em Java, para ambiente desktop usando classes Java Swing, e acedendo a
uma base de dados (BD) Oracle.
Este primeiro artigo trata da criao de uma pequena Base de Dados em Oracle. Foi usado o Oracle
Express 10g, o qual pode ser baixado gratuitamente em
http://www.oracle.com/technetwork/database/express-edition/downloads/102xewinsoft-
090667.html. H j uma verso mais recente do Oracle Express, a 11g release 2, a qual pode ser
obtida em http://www.oracle.com/technetwork/database/express-edition/downloads/index.html e
com a qual o exemplo tambm dever funcionar.
Aps a instalao do Oracle, podemos aceder ferramenta de administrao da base de dados indo
ao boto Iniciar --> Todos os Programas --
> Oracle Database 10g Express Edition --> Ir
para a Home Page de Banco de Dados ou, num
browser, ir a http://localhost:8080/apex.

Dever, ento, aparecer uma pgina para
efetuarmos o login na ferramenta de administrao:
Devemos entrar com o utilizador SYSTEM e o
password que definimos para esse utilizador
durante o processo de instalao.
Ap
s
ent
rar
apar
ece-
nos o
ambi
ente
de trabalho:



Neste ponto, devemos, primeiramente, criar um
utilizador (Administration --> Database
Users --> Create User). Crimos o
utilizador libraryuser, o qual ir ser, depois,
usado para criar as tabelas da BD e tambm para
aceder BD a partir da aplicao Java.

necessrio dar-lhe permisso de CREATE TABLE e
CREATE SEQUENCE, podendo tambm ser-lhe dada
permisso para CREATE VIEW, CREATE PROCEDURE,
e CREATE TRIGGER.
O user com que so criadas as tabelas da base de dados ir ficar como prefixo da tabela (schema)
e, dependendo dos direitos de acesso, pode ficar restringido a ver apenas as "suas" tabelas.

A referncia a uma coluna de uma tabela, em Oracle, tem a seguinte estrutura:
"schema"."table"."column"

O schema pode ter 30 bytes, o nome da tabela mais 30 bytes, e o nome da coluna mais 30 bytes.
O comprimento total mximo de um
identificador de coluna , portanto, de 98 bytes (se
contarmos os pontos e aspas).
No devemos, portanto, usar o user SYSTEM para
criar tabelas de utilizador, e muito menos para
aceder base de dados a partir de uma
aplicao.
Claro que para uma aplicao brinquedo isso no
importante.
O passo seguinte ser, ento, fazer logout de
SYSTEM na ferramenta de administrao, e
faze
r
login com o novo user criado (libraryuser).






Agora, podemos criar as tabelas da nossa base de dados, as quais iro ficar com schema
libraryuser, pois esse o utilizador que vamos usar na sua criao.











Queremos criar as tabelas conforme o seguinte
esquema de BD:





Exemplo de Aplicao Java Swing com BD Oracle - 2
No artigo anterior inicimos a construo de uma srie de artigos para a construo de uma pequena
aplicao exemplo de gesto de biblioteca, para ambiente desktop usando classes Java Swing, e
acedendo a uma base de dados (BD) Oracle.
O artigo anterior tratou da criao da Base de Dados em Oracle. Este artigo vai tratar da construo
de uma classe Java para acesso Base de Dados.
Iremos usar o NetBeans IDE 7.0.1, o qual pode ser baixado de
http://netbeans.org/community/releases/70/.

Aps instalar o NetBeans IDE 7.0.1, devemos criar um
novo projeto "Java Class Library", ao qual vamos
chamar HelperDB, pois ir tratar-se apenas de uma
classe de acesso base de dados.
Criamos uma classe Java, a que chamamos
DBAccessObj, a qual ficar no ficheiro
DBAccessObj.java.


necessrio incluir as bibliotecas de classes JAR para acesso por driver ODBC base de dados
Oracle:
Estes ficheiros jar devem estar presentes no diretrio:
oraclexe\app\oracle\product\10.2.0\server\jdbc\lib
sendo oraclexe o diretrio onde foi instalado o Oracle XE.

Vamos criar um package, a que chamamos HelperDB, que ir
conter a nossa classe, e vamos importar o package java.sql, o qual
contm classes de conexo e envio de statements SQL base de
dados:
package HelperDB;
import java.sql.*;
public class DBAccessObj {
private Connection conn;
public DBAccessObj() {
}
}

Como nica varivel de instncia da nossa classe, criamos conn do "tipo"java.sql.Connection.
Na verdade, Connection uma interface que poder conter um objeto de qualquer tipo que
implemente essa interface. Assim, conn poder conter uma instncia de uma conexo de qualquer
tipo. O tipo ser dado pelo DriverManager de acordo com o driver que for utilizado.
O construtor da classe ser ento modificado para criar uma conexo base de dados:

public DBAccessObj() {
this.createDBConnection();
}
private void createDBConnection() {
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
}
catch(ClassNotFoundException e) {
System.out.println("Oops! Can't find class oracle.jdbc.driver.OracleDriver");
System.exit(1);
}
try{
conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:XE",
"libraryuser","libraryuser");
}
catch(Exception e){
System.out.println("ERRO " + e.getMessage());
}
}

O driver a usar o "oracle.jdbc.driver.OracleDriver" e a string de ligao base de dados :
"jdbc:oracle:thin:@localhost:1521:XE"

sendo "libraryuser","libraryuser", respectivamente o user e password do utilizador que queremos
usar no acesso base de dados (ver artigo anterior).
Neste ponto, se fizermos uma pequena classe de teste (TestClass.java) para criar uma instncia da
nossa classe, j ser possvel ver se a conexo possvel:

import HelperDB.DBAccessObj;
public class TestClass {
public static void main(String[] args) {
DBAccessObj conexao = new DBAccessObj();
}
}

Se no for possvel, aparecer uma das mensagens de erro que damos num dos catchs acima.
Depois de criar a conexo base de dados queremos enviar statements SQL para inserir dados
numa tabela (INSERT), alterar dados (UPDATE), apagar dados (DELETE) ou consultar dados
(SELECT).

Para isso temos que ter uma instncia de uma classe que implemente a interface
java.sql.Statement:

public Statement createStatement() {
Statement st=null;
if (this.conn==null)
this.createDBConnection();
try{
st = this.conn.createStatement();
}
catch(Exception e){
System.out.println("ERRO " + e.getMessage());
}
return st;
}

Para executar um comando SQL usando a instncia de Statement, vamos criar mais uns mtodos
na nossa classe:

- Para executar um comando SQL que no devolve resultado (INSERT, UPDATE ou DELETE):

public void executeSQL(String SqlComm) {
Statement st = this.createStatement();
try {
st.execute(SqlComm);
}
catch(Exception e) {
System.out.println("ERRO " + e.getMessage());
}
}

- Para executar um comando SQL que devolve um resultado (SELECT):

public ResultSet executeQuery(String SqlComm) {
Statement st = this.createStatement();
ResultSet rs=null;
try {
rs = st.executeQuery(SqlComm);
}
catch(Exception e) {
System.out.println("ERRO " + e.getMessage());
}
return rs;
}

Por fim, vamos escrever mtodos para criar uma conexo e eliminar uma conexo:

public Connection openConnection() {
if(this.conn==null)
this.createDBConnection();
return this.conn;
}

public void closeConnection() {
if(this.conn!=null)
{
try{
this.conn.close();
}
catch(Exception e){
System.out.println("ERRO " + e.getMessage());
}
}
}

Isto termina a nossa classe. Para a testar, podemos agora melhorar a nossa classe de teste:

import HelperDB.DBAccessObj;
import java.sql.*;
public class TestClass {
public static void main(String[] args) {
DBAccessObj conexao = new DBAccessObj();
conexao.executeSQL("Insert into Author columns (Name, SURNAME) VALUES ('XICO',
'MENDES')");
ResultSet rs = conexao.executeQuery("SELECT * FROM AUTHOR");
try{
while(rs.next()){
String aName = ((String)rs.getString("Name"));
String aSurname = ((String)rs.getString("Surname"));
//
System.out.println(aName + " " + aSurname);
}
}
catch(Exception e){
System.out.println("ERRO " + e.getMessage());
}
}
}

Se tudo estiver bem, o resultado do teste ser a insero do autor com nome XICO MENDES na
tabela AUTHOR e a posterior listagem do contedo da mesma tabela.
No foram testados os mtodos de criar e fechar a conexo, mas veremos a sua utilidade noutro
artigo.

Exemplo de Aplicao Java Swing com BD Oracle 3
Hoje, vamos desenvolver uma biblioteca de classes que mapeia os conceitos do domnio do
problema, e faz a ponte entre a interface com o utilizador, cujo desenvolvimento trataremos no
prximo artigo, e a camada de persistncia de dados, tratada no primeiro artigo desta srie.

Esta camada com conceitos e operaes do domnio do problema comumente chamada de camada
intermdia ou camada de lgica do negcio.
Podemos considerar que o nosso pequeno sistema aplicacional ter, ento, uma arquitetura de
software em 3-camadas (abordaremos o tema da arquitetura de software num artigo futuro).
H vrias maneiras de desenvolver esta camada intermdia, a qual pode ela prpria conter uma ou
mais camadas. Ns iremos desenvolver uma classe para cada conceito do domnio, o que
corresponde, mais ou menos, neste pequeno exemplo, a desenvolver uma classe para cada tabela da
base de dados.

H vrias maneiras de fazer isso. Em particular, vamos ver duas possveis maneiras, cada uma com
o seu grupo de defensores, e com as suas prprias vantagens e desvantagens.
1 H autores que defendem o desenvolvimento de uma camada de classes apenas com atributos,
getters e setters (ex.: classe Book abaixo), separadamente de uma camada de classes com
operaes com significado para o negcio (ex.: classe BookBLL abaixo).
1.1 classe Book:
public class Book {
private int idBook;
private String title;
private String editor;
private java.sql.Date date;
private String ISBN;
private String edition;
//
private List<Author> authors = new ArrayList<Author>();
public Book() {}
public int getID() {return this.idBook; }
public void setTitle(String title) {this.title = title;}
public String getTitle() {return title; }
public void setEditor(String editor) {this.editor = editor;}
public String getEditor() {return editor;}
public void setDate(java.sql.Date date) {this.date = date;}
public java.sql.Date getDate() {return date;}
public void setISBN(String ISBN) {this.ISBN = ISBN;}
public String getISBN() {return ISBN;}
public void setEdition(String edition) {this.edition = edition;}
public String getEdition() {return edition;}
public List<Author> getAuthors() {return this.authors;}
}

1.2 classe BookBLL:

public class BookBLL {
private DBAccessObj dbo;
public BookBLL() {
this.dbo = new DBAccessObj();
this.dbo.openConnection();
}
public BookBLL(DBAccessObj dbo) {
this.dbo = dbo;
this.dbo.openConnection();
}
public void create(Book b) throws SQLException{
String sqlCommand =
"INSERT INTO Book (ISBN, Title, Edition, Editor) VALUES('" +
b.getISBN() + "', '" + b.getTitle() + "', '" +
b. getEdition() + "', '" + b.getEditor() + "')";
this.dbo.executeSQL(sqlCommand);
}

// restantes operaes

}

Esta primeira abordagem no explora o encapsulamento de dados e operaes sobre os dados
(conceito fundamental do paradigma de programao orientado a objetos).


2 Outra maneira, desenvolver:
uma camada de classes com atributos, getters e setters, mais as operaes CRUD(Create,
Retrieve, Update, Delete) (ex.: class BookDAL abaixo); separadamente de,
uma camada de classes com operaes com significado para o negcio, e que no dependem
directamente da base de dados e podem ser obtidas por composio das operaes CRUD primitivas
(ex.: class BookBLL abaixo).

2.1 classe BookDAL:

public class BookDAL {
private int idBook;
private String title;
private String editor;
private java.sql.Date date;
private String ISBN;
private String edition;
//
private List<Author> authors = new ArrayList<Author>();
private DBAccessObj dbo;
public BookDAL() {
this.dbo = new DBAccessObj();
this.dbo.openConnection();
}
public BookDAL(DBAccessObj dbo) {
this.dbo = dbo;
this.dbo.openConnection();
}
public int getID() {return this.idBook;}
public void setTitle(String title) {this.title = title;}
public String getTitle() {return title; }
public void setEditor(String editor) {this.editor = editor;}
public String getEditor() {return editor; }
public void setDate(java.sql.Date date) {this.date = date;}
public java.sql.Date getDate() {return date;}
public void setISBN(String ISBN) {this.ISBN = ISBN;}
public String getISBN() {return ISBN;}
public void setEdition(String edition) {this.edition = edition;}
public String getEdition() {return edition;}
public List<Author> getAuthors() {return this.authors;}
public void create() throws SQLException{
String sqlCommand =
"INSERT INTO Book (ISBN, Title, Edition, Editor) VALUES('" +
this.ISBN + "', '" + this.title + "', '" + this.edition + "', '" + this.editor + "')";
this.dbo.executeSQL(sqlCommand);
}
public void retrieve(int id) throws SQLException{
String sqlCommand =
"SELECT ISBN, Title, DateEdition, Edition, Editor FROM Book WHERE ID = '" + id + "'";
ResultSet book;
book = this.dbo.executeQuery(sqlCommand);
if (book.next()){
this.idBook = id;
this.ISBN = book.getString("ISBN");
this.title = book.getString("Title");
this.date = book.getDate("DateEdition");
this.edition = book.getString("Edition");
this.editor = book.getString("Editor");
}
}
public void retrieveByISBN(String isbn) throws SQLException{
String sqlCommand =
"SELECT ID, Title, DateEdition, Edition, Editor FROM Book WHERE ISBN = '" + isbn + "'";
ResultSet book;
book = this.dbo.executeQuery(sqlCommand);
if (book.next()){
this.idBook = book.getInt("ID");
this.title = book.getString("Title");
this.date = book.getDate("DateEdition");
this.edition = book.getString("Edition");
this.editor = book.getString("Editor");
this.ISBN = isbn;
}
}
public void update() {
String sqlCommand =
"UPDATE Book SET ISBN = '" + this.ISBN + "', Title = '" + this.title + "', Edition = '" +
this.edition + "', Editor = '" + this.editor + "' WHERE ID = '" + this.idBook + "'";

this.dbo.executeSQL(sqlCommand);
}
public void delete() {
String sqlCommand = "DELETE FROM Book WHERE ID = '" + this.idBook + "'";
this.dbo.executeSQL(sqlCommand);
}
public ResultSet retrieveThisBookAuthors(DBAccessObj dbo) throws SQLException{
String sqlCommand =
"SELECT B.ID, B.ISBN, B.Title, A.ID, A.Name, A.Surname FROM BookAuthor BA, Author A,
Book B WHERE BA.BookID = B.ID AND BA.AuthorID = A.ID AND B.ID = " + this.getID() + " ORDER
BY 3, 2";
ResultSet books;
dbo.openConnection();
books = dbo.executeQuery(sqlCommand);
return books;
}
public void fillThisBookAuthors() throws SQLException{
String sqlCommand = "SELECT A.ID, A.Name, A.Surname FROM BookAuthor BA, Author A,
Book B WHERE BA.BookID = B.ID AND BA.AuthorID = A.ID AND B.ID = " + this.getID() + " ORDER
BY 3, 2";
ResultSet booksA;
this.dbo.openConnection();
booksA = this.dbo.executeQuery(sqlCommand);
while (booksA.next()){
Author au = new Author();
au.setName(booksA.getString("Name"));
au.setSurname(booksA.getString("Surname"));
this.authors.add(au);
}
}
public static ResultSet retrieveAllBooks(DBAccessObj dbo) throws SQLException{
String sqlCommand = "SELECT ISBN, Title, DateEdition, Edition, Editor FROM Book";
ResultSet books;
dbo.openConnection();
books = dbo.executeQuery(sqlCommand);
return books;
}
public static ResultSet retrieveAllBooksAuthors(DBAccessObj dbo) throws SQLException{
String sqlCommand = "SELECT B.ID, B.ISBN, B.Title, A.ID, A.Name, A.Surname FROM
BookAuthor BA, Author A, Book B WHERE BA.BookID = B.ID AND BA.AuthorID = A.ID ORDER BY 1,
6, 5";
ResultSet books;
dbo.openConnection();
books = dbo.executeQuery(sqlCommand);
return books;
}

2.2 classe ManageBooksBLL:

public class ManageBooksBLL {
public ManageBooksBLL () {}
public int requisitarBook (Book book, Borrower leitor) throws ManageBookException {

}
public int requisitarBook (int bookID, int leitorID) throws ManageBookException {
}
public int devolverBook (Book book) throws ManageBookException{

}
public int devolverBook (int bookID) throws ManageBookException {

}
}

Nesta abordagem, o encapsulamento de dados e operaes
aparece, orientado s entidades do domnio do problema (classes
Entidade ou persistentes), na camada DAL.
A camada BLL (Business Logic Layer) contm operaes
orientadas aos casos de uso a implementar na aplicao, podendo
portanto ser vista como uma camada de fornecimento de servios
para a camada acima, de Interface com o utilizador (UI, User
Interface).
Em termos prticos, dependendo da quantidade de operaes
complexas num programa (diferentes de CRUD), podemos ainda
misturar a DAL e BLL da 2 abordagem, passando isso por acrescentar nas classes DAL os poucos
mtodos BLL que tivssemos, eliminando as classes BLL.
De notar, em ambas as abordagens, a utilizao da classe DBAccessObj, cujo desenvolvimento foi
tratado no artigo anterior, para acesso base de dados.
O zip com o resultado final pode, como de costume, ser solicitado nos comentrios a este artigo.

Exemplo de Aplicao Java Swing com BD Oracle 4
Neste artigo vamos desenvolver a camada de apresentao, ou de Interface com o utilizador, para a
aplicao que vem sendo desenvolvida h algum tempo.
No artigo Exemplo de Aplicao Java Swing com BD Oracle - 1, o 1 desta srie, tratmos da criao
da Base de Dados em Oracle. No 2 artigo, foi criada um package para acesso base de dados,
HelperDB. O 3 artigo tratou da criao de uma biblioteca de classes ao nvel da lgica de negcio e
acesso a dados.
Este artigo vai tratar da criao do projecto de Interface com o utilizador (GUI - Graphical User
Interface) usando classes Swing. Para isso, vamos
criar um novo projecto no Net Beans,
chamado LibrarySystem:
Este projecto deve ser um Java Desktop
Application. Este tipo de projecto fornece um
template com a infraestrutura bsica de uma aplicao
desktop, tal como uma janela principal com uma barra
de menu e uma barra de estado.
Depois, vamos seleccionar Basic Application (o
outro tipo, Database Application, iremos abordar
numa outra srie de artigos).





Este tipo de projeto cria de antemo 3 classes:

- LibrarySystemApp.java - a classe principal da aplicao. A main ir lanar a janela principal. A
partir da, toda a aplicao ser guiada por eventos.
- LibrarySystemView.java - a janela principal:
- LibrarySystemAboutBox.java - uma janela
About (Acerca de...).











Na janela com a vista de projectos podemos ver o novo
projecto, assim como os que crimos anteriormente. Para
mantr uma lgica nos nomes dos projectos, altermos o nome
deste projecto para libraryProjectGUI:

1. Construo da interface (GUI)

A partir da Pallete (onde esto os Swing containers,
Swing controls, Swing Windows, etc.), arrastamos os
objectos de interface que pretendemos ver nas
janelas da interface.


Aqui, vamos fazer toda a aplicao na mesma janela.
Vamos comear por acrescentar menus (JMenu) e
itens de menu (JMenuItem) na barra de menus que
j temos inicialmente.






Criamos um item de menu, Initial Panel, no menu
File, que nos permitir voltar ao ecr inicial:


E criamos um novo menu, Books, com um item de
menu, Manage Books, o qual nos levar lista e
manute
no
de
livros
da
biblioteca:



Chegou, ento o momento de criar novos painis
(JPanel) que substituiro o painel inicial na janela da
aplicao.
Criamos um novo painel para criao e edio de um
livro:












E, criamos um painel para listar os livros existentes:





2. Criao de mtodos para tratamento de eventos
despoletados na GUI
Vamos agora fazer trocar o painel visvel, quando selecionada a opo de menu Manage Books do
menu Books.
Quando ocorre um evento "selecionar o item de menu" queremos correr um mtodo para fazer a
troca de painis. Temos duas maneiras de o fazer:
2.1 Com o boto do lado direito sobre o item de
menu Manage Books, selecionamos Events --
> Action --> actionPerformed:

Isto provoca a gerao de cdigo na classe
LibrarySystemView.java, associando um novo mtodo
ao evento de seleo do item de menu, e criando um
template para esse novo mtodo:

private void jMenuItem1ActionPerformed(java.awt.event.ActionEvent evt)
{
// TODO add your handling code here:
}
2.2 Com o boto do lado direito sobre o item de
menu Manage Books, selecionamosSetAction. Isto
conduz-nos a uma janela para entrada de detalhes
sobre o cdigo que ir ser gerado:




Em Action, selecionamos Create New Action, e
em Action's Method, escrevemoslistBooks. O mtodo
listBooks() ser criado de novo, e ser associado ao
evento de seleo do item de menu.

@Action
public void listBooks() {
}
No mtodo listBooks(), ou
no jMenuItem1ActionPerformed() se optarmos pelo
primeiro mtodo, vamos colocar o cdigo para troca de
painis.

@Action
public void listBooks() {
ListBooksJPanel listbooksP = new ListBooksJPanel(this, this.dbo);
this.visiblePanel.setVisible(false);
this.visiblePanel = listbooksP;
listbooksP.setVisible(true);
this.getFrame().setContentPane(listbooksP);
this.getFrame().repaint();
//
}

Antes, tivmos que criar as variveis de instncia seguintes na classe LibrarySystemView:

private HelperDB.DBAccessObj dbo;
private JPanel visiblePanel = null;

tambm necessrio criar cdigo para ler os livros da base de dados e preencher a tabela no
painel ListBooksJPanel. Para isso devem ser usadas as classes da biblioteca de classes criada no
artigo anterior.
Se tiverem dificuldades com o cdigo ou quiserem as sources do exemplo, coloquem comentrios a
este post.

Outros artigos relacionados:
- Exemplo de Aplicao Java Swing com BD Oracle - 1
- Exemplo de Aplicao Java Swing com BD Oracle - 2
- Exemplo de Aplicao Java Swing com BD Oracle - 3
- Exemplo de Aplicacao Java Swing com BD Oracle - 4

Publicada por Miguel Cruz (s) 2/06/2012 12:22:00 PM