Lista de Códigos
7.3 Modelo de dados relacional
7.3.2 JDBC
A linguagemSQL pode ser utilizada diretamente pelo usuário, quando o SGBD oferece um interpretadorSQL interativo ou através de comandos embutidos em uma aplicação desenvolvida em uma linguagem de programação. No caso da linguagem de programação Java, a forma de interagir com o banco de dados é especificada pela API JDBC (SPEEGLE, 2001), discutida nesta seção.
O Java Database Connectivity (JDBC) é uma APIJava (pacote java.sql) para execução e manipulação de resultados de consultas SQL. Para uma aplicação Java acessar um banco de dados relacional é necessária a execução dos seguintes passos:
1. habilitar odriver JDBC;
2. estabelecer uma conexão com o banco de dados;
3. executar a consultaSQL; e 4. apresentar resultados da consulta.
7.3.2.1 Drivers JDBC
O driver JDBC consiste em um componente de software que permite que uma aplicação Java interaja com um banco de dados. Para conectar com banco de dados individuais, o JDBC requer drivers para cada SGBD (PostgreSQL, MySQL, etc.).
O driver JDBC fornece a conexão ao banco de dados e implementa o protocolo para transferir a consulta e o resultado entre a aplicação-cliente Java e oSGBD.
Do ponto de vista da aplicação Java, um driver nada mais é do que uma classe cuja funcionalidade precisa ser disponibilizada para a aplicação. A funcionalidade básica que um driver deve oferecer é especificada através da interface Driver. A forma mais usual é carregar odriver explicitamente para a JVM através do método forName()da classe Class, como em
Class.forName("org.postgresql.Driver"); // Carrega odriverpara o SGBD PostgreSQL Class.forName("com.mysql.jdbc.Driver"); // Carrega odriverpara o SGBD MySQL
Class.forName("org.apache.derby.jdbc.ClientDriver"); // Carrega odriverpara o SGBD Apache Derby
Alternativamente, a classe DriverManager estabelece um conjunto básico de serviços para a manipulação de drivers JDBC. Como parte de sua inicialização, essa 184
classe tentará obter o valor da propriedadejdbc.driversde um arquivo de definição de propriedades e carregar os driversespecificados pelos nomes das classes.
7.3.2.2 Conexão com banco de dados
Uma vez que o driver esteja carregado, a aplicação Java pode estabelecer uma conexão com o sistema gerenciador de banco de dados. Para especificar com qual banco de dados se deseja estabelecer a conexão, é utilizada uma string na forma de uma URL na qual o protocolo é jdbc: e o restante da string é dependente do driver. Por exemplo, aURL jdbc:derby://localhost:1527/Museu, especifica uma conexão ao banco de dadosMuseuque se encontra sob a gerência doSGBD Apache Derbyhospedado na máquina local.
Identificado o banco de dados, a sessão, a ser estabelecida para o acesso ao banco de dados, será controlada por uma instância de uma classe que implementa a interface Connection. ODriverManageroferece o métodogetConnection()para executar essa tarefa. O encerramento de uma sessão é sinalizado pelo método close() da conexão.
String url = "jdbc:derby://localhost:1527/Museu"; // URL de conexão String usuário = "root"; // usuário do SGBD
String senha = "root"; // senha do usuário do SGBD ...
Connection c = DriverManager.getConnection(url, usuário, senha);
...
c.close(); // encerra a conexão com o banco
7.3.2.3 Execução da consulta
Estabelecida a conexão ao banco de dados, é possível criar uma consulta SQL e executá-la a partir da aplicação Java. Para representar uma consulta SQL, o JDBC utiliza uma instância de uma classe que implementa a interface Statement. Um objeto dessa classe pode ser obtido através do métodocreateStatement()da classe Connection.
Uma vez que uma instância de Statement esteja disponível, é possível aplicar a ele o método executeQuery(), que recebe como argumento uma string repre- sentando uma consultaSQL. O resultado da execução da consulta é disponibilizado através de um objetoResultSet.
185
...
Connection c = DriverManager.getConnection(url, usuário, senha);
..
Statement s = c.createStatement();
String query = "SELECT * FROM Empregado";
ResultSet r = s.executeQuery(query);
...
s.close();
c.close(); // encerra a conexão com o banco
Os métodos da interface ResultSet permitem a manipulação dos resultados individuais de uma tabela de resultados. Métodos como getDouble(), getInt() e getString(), que recebem como argumento a especificação de uma coluna da tabela, permitem acessar o valor da coluna especificada na tupla corrente para os diversos tipos de dados suportados.
Para varrer a tabela, um cursor é mantido. Inicialmente, ele está posicionado antes do início da tabela, mas pode ser manipulado pelos métodosfirst(),next(), previous(),last()eabsolute(int row). Por exemplo,
ResultSet r = s.executeQuery("SELECT * FROM EMPREGADO");
System.out.println("Id Nome");
while (r.next()) { System.out.println(r.getString("Id")+ + r.getString("Nome")); } r.close();
Para lidar com atributos que podem assumir valores nulos, o método wasNull() é oferecido. Ele retorna verdadeiro quando o valor obtido pelo métodogetXXX()for nulo, em queXXXé um dos tipos SQL.
A interface ResultSetMetadata permite obter informação sobre a tabela com o resultado da consulta. Um objeto desse tipo pode ser obtido através da aplicação do método getMetaData() ao ResultSet. Uma vez obtido esse objeto, a infor- mação desejada pode ser obtida através de métodos tais comogetColumnCount(), getColumnLabel(),getColumnTypeName()egetColumnType(). O último método retorna tipos que podem ser identificados a partir de constantes definidas na classe java.sql.Types.
Além da forma interface Statement, JDBC oferece duas formas alternativas que permitem, respectivamente, ter acesso a comandos SQL pré-compilados (PreparedStatement) e a procedimentos armazenados no banco de dados (CallableStatement).
186
7.3.2.4 AplicaçãoListaObrasDeArte
Esta seção apresenta uma aplicação Java (Código 7.2) que acessa o banco de dadosMuseu hospedado na máquina local. Com propósitos de ilustração, o Apache Derby2será utilizado nessa aplicação. No entanto, o leitor deve sentir-se à vontade para usar outro SGBD se este já estiver instalado e configurado. Os links abaixo apresentam dicas na configuração do Apache Derby e na posterior integração com os dois principaisIDEs open-source:
• Netbeans: https://netbeans.org/kb/docs/ide/java-db_pt_BR.html.
• Eclipse: http://db.apache.org/derby/integrate/plugin_help/start_toc.html.
Essa aplicação supõe que o banco de dadosMuseufoi criado e populado conforme descrito no script apresentado no Código 7.1. A classe ListaObrasDeArte apenas possui o método main(), que simplesmente conecta com o banco de dados Museu e imprime a lista de obras de arte armazenada nesse banco de dados. A saída da execução desse programa é similar à apresentada na Tabela 7.1.
ID TITULO ARTISTA MATERIAL ANO CATEGORIA TIPO ALTURA
1 Mona Lisa Leonardo da Vinci Madeira 1503 1 Óleo null
2 David Michelangelo Mármore 1501 2 null 4,10
3 O Lavrador de Café Cândido Portinari Madeira 1939 1 Óleo null
4 O Pensador Auguste Rodin Bronze 1909 2 null 1,40
Tabela 7.1 Saída da execução da classeListaObrasDeArte.
Conforme se pode observar, o método main()executa os quatro passos neces- sários para acessar um banco de dados relacional utilizando aAPI JDBC:
1. habilitar odriver JDBC(linha 14);
2. estabelecer uma conexão com o banco de dados (linhas 16-21);
3. executar a consultaSQL (linhas 23-25); e 4. apresentar resultados da consulta (linhas 27-61).
2 http://db.apache.org/derby/.
187
1 /∗∗
∗ C l a s s e L i s t a O b r a s D e A r t e−− C o n e c t a com o b a n c o de d a d o s Museu e i m p r i m e a l i s t a de o b r a s de a r t e 2 3
∗ a r m a z e n a d a na t a b e l a O b r a D e A r t e p r e s e n t e n e s s e b a n c o de d a d o s .
∗ 4
5
∗ @ a u t h o r D e l a n o M e d e i r o s B e d e r
6
∗/
7 p u b l i c c l a s s L i s t a O b r a s D e A r t e {
8 9 p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) {
10 f i n a l S t r i n g f m t 1 0 = " %−10.10 s " ;
11 f i n a l S t r i n g f m t 2 0 = " %−20.20 s " ;
12 13 t r y {
14 C l a s s . forName ( d r i v e r ) ; // C a r r e g a d r i v e r
15 16 // E s t a b e l e c e c o n e xão com o b a n c o de d a d o s
17 S t r i n g d r i v e r = " o r g . a p a c h e . d e r b y . j d b c . C l i e n t D r i v e r " ;
18 S t r i n g u r l = " j d b c : d e r b y : / / l o c a l h o s t : 1 5 2 7 / Museu " ;
19 S t r i n g u s e r = " r o o t " ;
20 S t r i n g p a s s w o r d = " r o o t " ;
21 C o n n e c t i o n c o n n e c t i o n = D r i v e r M a n a g e r . g e t C o n n e c t i o n ( u r l , u s e r , p a s s w o r d ) ;
22 23 // Monta e e x e c u t a c o n s u l t a
24 S t a t e m e n t s = c o n n e c t i o n . c r e a t e S t a t e m e n t ( ) ;
25 R e s u l t S e t r = s . e x e c u t e Q u e r y ( "SELECT ∗FROM O b r a D e A r t e " ) ;
26 27 // A p r e s e n t a e s t r u t u r a da T a b e l a
28 S t r i n g B u i l d e r s b =new S t r i n g B u i l d e r ( ) ;
29 f o r (i n t i = 0 ; i < 1 2 ; i ++) {
30 s b . a p p e n d ( "−−−−−−−−−−" ) ;
31 }
32 S y s t e m . o u t . p r i n t l n ( s b ) ;
33 34 R e s u l t S e t M e t a D a t a m = r . g e t M e t a D a t a ( ) ;
35 i n t c o l C o u n t = m. g e t C o l u m n C o u n t ( ) ;
36 f o r (i n t i = 1 ; i <= c o l C o u n t ; ++i ) {
37 i f (m. g e t C o l u m n T y p e ( i ) != T y p e s . VARCHAR) {
38 S y s t e m . o u t . p r i n t f ( fmt10 , m. getColumnName ( i ) ) ;
39 } e l s e {
40 S y s t e m . o u t . p r i n t f ( fmt20 , m. getColumnName ( i ) ) ;
41 }
42 }
43 S y s t e m . o u t . p r i n t l n ( ) ;
44 S y s t e m . o u t . p r i n t l n ( s b ) ;
45 46 w h i l e ( r . n e x t ( ) ) {
47 S y s t e m . o u t . p r i n t f ( fmt10 , S t r i n g . v a l u e O f ( r . g e t I n t ( 1 ) ) ) ; // Obtém p e l o número da c o l u n a
48 S y s t e m . o u t . p r i n t f ( fmt20 , r . g e t S t r i n g ( "TITULO" ) ) ; // Obtém p e l o nome da c o l u n a
49 S y s t e m . o u t . p r i n t f ( fmt20 , r . g e t S t r i n g ( 3 ) ) ; // Obtém p e l o número da c o l u n a
50 S y s t e m . o u t . p r i n t f ( fmt20 , r . g e t S t r i n g ( "MATERIAL" ) ) ; // Obtém p e l o nome da c o l u n a
51 S y s t e m . o u t . p r i n t f ( fmt10 , S t r i n g . v a l u e O f ( r . g e t I n t ( 5 ) ) ) ; // Obtém p e l o número da c o l u n a
52 S y s t e m . o u t . p r i n t f ( fmt10 , S t r i n g . v a l u e O f ( r . g e t I n t ( 6 ) ) ) ; // Obtém p e l o número da c o l u n a
53 S y s t e m . o u t . p r i n t f ( fmt20 , r . g e t S t r i n g ( " TIPO " ) ) ; // Obtém p e l o nome da c o l u n a
54 d o u b l e a l t u r a = r . g e t D o u b l e ( 8 ) ; // Obtém p e l o número da c o l u n a
55 56 i f ( a l t u r a == 0 ) {
57 S y s t e m . o u t . p r i n t f ( f m t 1 0+" \ n " , " n u l l " ) ;
58 } e l s e {
59 S y s t e m . o u t . p r i n t f ( " %−10.2 f \ n " , r . g e t D o u b l e ( 8 ) ) ;
60 }
61 }
62 r . c l o s e ( ) ;
63 c o n n e c t i o n . c l o s e ( ) ; // F e c h a c o n e xão com b a n c o de d a d o s
64 } c a t c h ( E x c e p t i o n e ) {
65 S y s t e m . e r r . p r i n t l n ( e ) ;
66 }
67 }
68
}
Código 7.2 ClasseListaObrasDeArte.
188