RSS

Arquivo da categoria: Estudos Java

Trabalhos e projetos em java

Acessando o Bco Interbase/Firebird

Read the rest of this entry »

 
Deixe um comentário

Publicado por em 10/02/2010 em Estudos Java

 

Arvore Binária Java

    Read the rest of this entry »

     
    Deixe um comentário

    Publicado por em 01/12/2009 em Estudos Java

     

    Aprende-se a programar bem sabendo o que não se deve fazer

    Read the rest of this entry »

     
    Deixe um comentário

    Publicado por em 23/11/2009 em Estudos Java

     

    Fundamentos da POO “Programação Orientada a Objetos”

    A programação Orientada a Objetos e uma forma especial de programar o mais próximos de como expressaríamos em nossas vidas reais, de que outras programação.
    Com a POO temos de pensar em coisas de uma maneira mais simples, para que possamos programar em termos de objetos, propriedades, métodos, e outras coisas que passarei a vocês rapidamente para que possamos entender melhor e nos sentirmos mais a vontade a este tipo de programação.
    Motivação:
    Durante muito tempo os programadores se dedicaram a desenvolver aplicações muito parecidas que resolviam uma vez ou outra seus problemas. Para ver seus esforços de programadores como eu e vocês possam ser utilizados por outras pessoas foi criada a POO, uma série de normas de realizar as coisas de maneiras e possibilidades que outras pessoas possam utilizar adiantando seu trabalho, de maneira que qualquer outro programador possa reaproveitar seus códigos.
    A POO não é difícil, mas é uma maneira especial de pensar em programação, as vezes subjetiva do programador, embora podemos criar programas de formas diferentes, nem todas elas são as corretas, o difícil não é programar orientado a objetos e sim, programar bem, programar bem e importante pois podemos aproveitar todas as vantagens da POO.
    Como pensar em Objetos:
    Pensar em termos de objetos é muito parecido com a vida real, onde, por exemplo, pensaríamos em uma “pizza”, para criar um modelo de POO. Falaríamos que a pizza é o elemento principal que tem uma série de características, que poderiam ser tamanho, recheio ou pedaços, e outras funcionalidades que a acompanhariam como, refrigerante, talhares, pratos, copos, dentre outras que poderiam ser utilizadas.
    Então em um esquema de POO a pizza seria o objeto, e as propriedades seriam as características, como tamanho, recheio e os métodos seriam as funcionalidades associadas como refrigerantes, talhares…
    Por dar outro exemplo, vamos ver como faríamos um modelo em um esquema POO de uma fração, ou seja, essa estrutura matemática que tem um numerador e um denominador que divide ao numerador, por exemplo, 5/6.
    A fração será o objeto e terá duas propriedades, o numerador e o denominador. Logo, poderia ter vários métodos como simplificar, somar com outra fração ou número, subtrair com outra fração, etc.
    Estes objetos poderão ser utilizados nos programas, por exemplo, em um programa de matemáticas seria feito o uso de objetos fração e em um programa que providencie um restaurante, seria utilizado o uso de objeto pizza. Os programas Orientados a objetos utilizam muitos objetos para realizar as ações que se desejam realizar e eles mesmos também são objetos. O restaurante será o objeto que utilizara objetos pizza, macarronada, garçons, etc.
    Classe em POO:
    As classes são declarações de objetos, também se poderiam definir como abstrações de objetos. Definindo, objeto é a classe. Quando programamos um objeto e definimos suas características e métodos na verdade estamos programando uma classe. Nos exemplos anteriores na verdade falávamos de classes, Pizza e Fração, porque somente estivemos definindo, embora por alto suas formas.
    Métodos nas classes:
    Seriam as funcionalidades associadas aos objetos. Quando estivermos programando as classes as chamamos de métodos. Os métodos seriam como funções que estão associadas a um objeto.
    Objetos em POO:
    São exemplares apartir de uma classe qualquer, quando criamos um exemplar temos que especificar a classe a partir da qual se criara. Esta ação de criar um objeto a partir de uma classe se chama instance (que significa em inglês exemplificar). Por exemplo, um objetivo da classe fração, por exemplo, 5/6. a definição de fração seria a classe, mas quando já estávamos falando de uma fração em concreto 1/2, 5/1000 ou outra qualquer chamamos de objeto.
    Para criar um objeto temos de escrever a instrução especial que possa ser distinta dependendo da linguagem de programação que se empregue, mas será algo parecido a isto.
    minhaPizza = new Pizza()
    Com a palavra new especificamos que se tem que criar uma instance da classe que continua a seguir. Dentro dos parênteses poderíamos colocar parâmetros com os quais se inicia o objeto da classe pizza.
    Para acessar a um estado de um objeto para ver seu valor ou muda-lo se utiliza o operador ponto.
    minhaPizza.tamanho = grande
    O objeto é minhaPizza, logo colocamos o operador ponto e por ultimo o nome da propriedade a qual desejamos acessar. No exemplo estamos mudando o valor do estado da propriedade do objeto a grande com uma pequena atribuição.
    Mensagens em objetos:
    Uma mensagem em um objeto é a ação de efetuar uma chamada a um método. Por exemplo, quando dizemos a um objeto pizza qual seu tamanho, estamos lhe passando a mensagem “tamanho”.
    Para mandar mensagens aos objetos utilizaremos o operador ponto, seguido do método que desejamos utilizar.
    minhaPizza.tamanho()
    Neste exemplo, passamos a mensagem tamanho(). Deve-se colocar parênteses assim como com qualquer chamada a uma função, dentro iriam os parâmetros.
    O que foi visto neste pequeno tutorial foi somente uma referencia a POO, também existe mecanismos como herança e poliformismo que são umas das possibilidades mais potentes de POO.
    Que são conceitos avançados que custa explicar nas linhas deste pequeno tutorial, não deveremos esquecer que existem livros inteiros dedicados a POO e aqui somente pretendia dar uma idéia a algumas coisas para que se lembrem quando estiver diante delas nas linguagens de programação que deve conhecer um programador Java.

     
    Deixe um comentário

    Publicado por em 23/11/2009 em Estudos Java

     

    Criando uma conexão através do Driver ODBC

    import java.sql.*; 

    public class simpleConnection {  

    public static void main(String args[]) {  

    try {  

    //Registrando o driver:

                 Class.forName("sun.jdbc.odbc.JdbcOdbcDriver").newInstance();  

    //Estabelecendo a conexão através do ODBC criado no Painel de Controle:

                 Connection con = DriverManager.getConnection("jdbc:odbc:Inventory","",""); 

    //Criando um objeto Statement para enviar requisições SQL para o Banco de Dados

                 Statement stmt = con.createStatement(); 

    //Executando SQL:

                 stmt.execute("SELECT * FROM objects"); 

    //Adquirindo através de um objeto ResulSet, os registros retornados pela SQL:

                 ResultSet results = stmt.getResultSet(); 

    //Fechando a conexão:

                 con.close(); 

              } catch(Exception e) {  

                 System.out.println(e);  

              } 

           } 

        }

     
    Deixe um comentário

    Publicado por em 23/11/2009 em Estudos Java

     

    Conexão Java + Interbase

    import java.sql.*; 

    public class Bco { 

    public static void main(String args[]) { 

    System.out.println(“#testando acesso a banco de dado Interbase “); 

    Connection conn = null; 

    String teste = “SELECT NOME FROM TAB_CLI_001;”; 

    try { 

    Class.forName(“org.firebirdsql.jdbc.FBDriver”); 

    conn = 

    DriverManager.getConnection( 

    “jdbc:firebirdsql:ip_do_servidor/3050:/caminho_do_bco_de_dados.gdb”,  “SYSDBA”,  “masterkey”); 

    System.out.println(“Sucesso na conexão! Massacre! “); 

    Statement stm = conn.createStatement(); 

    ResultSet rs = stm.executeQuery(teste); 

    while (rs.next()) { 

    String linha = rs.getString(“NOME”); 

    System.out.println(“Cliente:” + linha); 

           } 

    System.out.println(“select realizado “); 

    } catch (ClassNotFoundException e) { 

    System.out.println(“excessao ClassNotFound…”); 

    e.printStackTrace(); 

    } catch (SQLException e) { 

    System.out.println(“SQL Exception… Erro dos Bravos”); 

    e.printStackTrace(); 

    } finally { 

    try { 

    conn.close(); 

    } catch (SQLException onConClose) { 

    System.out.println(“error on closing”); 

    onConClose.printStackTrace(); 

           } 

         } 

       } 

    }

     
    Deixe um comentário

    Publicado por em 23/11/2009 em Estudos Java

     

    Analisando Metadados com JDBC

    Introdução

    Neste Tutorial você aprenderá a recuperar metadados de seu banco de dados, tabelas e stored procedures. Mas, o que são metadados? Como o próprio nome diz, Metadados são informações sobre os seus dados. Pense em metadata como um reflection do seu banco de dados! Ex: Metadados de uma tabela são: nome das colunas, tipo de dados das colunas (VARCHAR, NUMBER), tamanho da coluna, proprietário da tabela,etc.

    Motivação

    Em algumas situações é necessário se recuperar esses metadados para construirmos nossas consultas dinamicamente, pois em uma grande base de dados algumas mudanças estruturais podem ocorrer com certa frequência. Alguns desenvolvedores constróem seus próprios frameworks utilizando as funcionalidades de recuperação de metadados do JDBC. Assim quando um Analista de Dados alterar o modelo relacional, acrescentando colunas ou alterando o tipo das mesmas, as suas aplicações não precisam sofrer manutenções. Existem três classes que nos permitem recuperar metadados a partir do Driver JDBC, no pacote java.sql:

  1. DatabaseMetaData
  2. ResultSetMetaData
  3. ParameterMetaData (nova, JDBC 3.0)

    A Classe DatabaseMetaData

    A classe DatabaseMetaData é recuperada através do objeto Connection e nos permitirá recuperar metadados sobre o banco de dados em uso, objetos do banco de dados, informações sobre o Driver JDBC, privilégios de acesso, etc. Existem mais de 150 métodos disponíveis para esta classe. Vamos então verificar como utilizar a Classe DatabaseMetaData :

     

    1. package br.com.guj; 
    2.  
    3. import java.sql.*; 
    4.  
    5. public class Exemplo1 { 
    6. public static void main(String[] args) throws SQLException { 
    7. // registrar o Driver JDBC do banco de dados, neste caso estou usando o da Oracle
    8.         DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver()); 
    9.  
    10. // String de conexao para uma base Oracle
    11.         Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:orcl","scott","tiger"); 
    12.  
    13. // recuperar a classe  DatabaseMetadaData a partir da conexao criada
    14.         DatabaseMetaData dbmd = conn.getMetaData(); 
    15.  
    16.         System.out.println ( "Versao do Driver JDBC = "+ dbmd.getDriverVersion()); 
    17.         System.out.println ( "Versao do Banco de Dados = "+ dbmd.getDatabaseProductVersion()); 
    18.         System.out.println ( "Suporta Select for Update? = "+ dbmd.supportsSelectForUpdate());   
    19.         System.out.println ( "Suporta Transacoes? = "+ dbmd.supportsTransactions()); 
    20.  
    21. // retornar todos os schemas(usuarios) do Banco de Dados
    22.         ResultSet r2 = dbmd.getSchemas(); 
    23. while (r2.next()) { 
    24.             System.out.println("SCHEMA DO BD = " + r2.getString(1)); 
    25.         } 
    26.     } 

    package br.com.guj; import java.sql.*; public class Exemplo1 { public static void main(String[] args) throws SQLException { // registrar o Driver JDBC do banco de dados, neste caso estou usando o da Oracle DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver()); // String de conexao para uma base Oracle Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:orcl","scott","tiger"); // recuperar a classe DatabaseMetadaData a partir da conexao criada DatabaseMetaData dbmd = conn.getMetaData(); System.out.println ( "Versao do Driver JDBC = "+ dbmd.getDriverVersion()); System.out.println ( "Versao do Banco de Dados = "+ dbmd.getDatabaseProductVersion()); System.out.println ( "Suporta Select for Update? = "+ dbmd.supportsSelectForUpdate()); System.out.println ( "Suporta Transacoes? = "+ dbmd.supportsTransactions()); // retornar todos os schemas(usuarios) do Banco de Dados ResultSet r2 = dbmd.getSchemas(); while (r2.next()) { System.out.println("SCHEMA DO BD = " + r2.getString(1)); } } }

    A Classe ResultSetMetaData

    A outra Classe que pode ser utilizada para recuperar mais metadados é a ResultSetMetaData, com um objeto dessa classe você poderá dinamicamente recuperar a quantidade de colunas de uma tabela (não estou me referindo a registros ou linhas, e sim colunas), também poderá dinamicamente descobrir o nome da coluna, seu tipo, tamanho, entre outras informações. Neste próximo exemplo iremos utilizar a classe ResultSetMetaData para descobrirmos dinamicamente o total de colunas de uma tabela, o nome de suas colunas e o tipo das mesmas.

     

    1.   … 
    2. Statement stmt = conn.createStatement(); 
    3. // Tabela a ser analisada
    4. ResultSet rset = stmt.executeQuery("SELECT * from EMP "); 
    5.  
    6. ResultSetMetaData rsmd = rset.getMetaData(); 
    7.  
    8. // retorna o numero total de colunas
    9. int numColumns = rsmd.getColumnCount(); 
    10. System.out.println("Total de Colunas = " + numColumns); 
    11.  
    12. // loop para recuperar os metadados de cada coluna
    13. for (int i=0; i<numColumns; i++) { 
    14.     System.out.print("Nome da Coluna=" + rsmd.getColumnName (i + 1)); 
    15.     System.out.print(" Tipo=" + rsmd.getColumnType (i + 1) ); 
    16.     System.out.print(" Nome do Tipo=" + rsmd.getColumnTypeName (i + 1)); 
    17.     System.out.print(" Tamanho=" + rsmd.getColumnDisplaySize (i + 1)); 
    18.     System.out.println(" Casas Decimais=" + rsmd.getScale(i + 1)); 

    … Statement stmt = conn.createStatement(); // Tabela a ser analisada ResultSet rset = stmt.executeQuery("SELECT * from EMP "); ResultSetMetaData rsmd = rset.getMetaData(); // retorna o numero total de colunas int numColumns = rsmd.getColumnCount(); System.out.println("Total de Colunas = " + numColumns); // loop para recuperar os metadados de cada coluna for (int i=0; i<numColumns; i++) { System.out.print("Nome da Coluna=" + rsmd.getColumnName (i + 1)); System.out.print(" Tipo=" + rsmd.getColumnType (i + 1) ); System.out.print(" Nome do Tipo=" + rsmd.getColumnTypeName (i + 1)); System.out.print(" Tamanho=" + rsmd.getColumnDisplaySize (i + 1)); System.out.println(" Casas Decimais=" + rsmd.getScale(i + 1)); }
    Você ainda pode utilizar as classes PreparedStatement ou CallableStatement para uma instância ResultSetMetaData. Comprove no exemplo abaixo:

     

    1. … 
    2. PreparedStatement ps = conn.prepareStatement("SELECT * FROM EMP where EMPNO = ? "); 
    3. ps.setLong(1,1020L); 
    4.  
    5. ResultSetMetaData rsmd = ps.getMetaData(); 
    6.  
    7. // retorna o numero total de colunas
    8. int numColumns = rsmd.getColumnCount(); 
    9. System.out.println("Total de Colunas = " + numColumns); 

    … PreparedStatement ps = conn.prepareStatement("SELECT * FROM EMP where EMPNO = ? "); ps.setLong(1,1020L); ResultSetMetaData rsmd = ps.getMetaData(); // retorna o numero total de colunas int numColumns = rsmd.getColumnCount(); System.out.println("Total de Colunas = " + numColumns);

    A Classe ParameterMetaData

    Através da classe ParameterMetaData é possível recuperar metadados sobre os "parâmetros" de cláusulas SQL que usamos com a classe PreparedStatement. Assim poderemos descobrir dinamicamente a quantidade de parâmetros utilizados e suas características. Confiram no exemplo abaixo o uso da classe ParameterMetaData recuperando informações sobres os parâmetros "?" da clásula SQL.

     

    1. PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM EMP WHERE EMPNO = ? AND DEPTNO = ?"); 
    2. ParameterMetaData pmd = pstmt.getParameterMetaData(); 
    3.  
    4. // recupera o total de parametros
    5. int totalParam = pmd.getParameterCount(); 
    6.  
    7. // recupera informacoes sobre cada parametro
    8. for (int i=0; i < totalParam; i++) { 
    9. int tipoParam = pmd.getParameterType(i+1); 
    10.     String nomeTipoParam = pmd.getParameterTypeName(i+1); 

    PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM EMP WHERE EMPNO = ? AND DEPTNO = ?"); ParameterMetaData pmd = pstmt.getParameterMetaData(); // recupera o total de parametros int totalParam = pmd.getParameterCount(); // recupera informacoes sobre cada parametro for (int i=0; i < totalParam; i++) { int tipoParam = pmd.getParameterType(i+1); String nomeTipoParam = pmd.getParameterTypeName(i+1); }

    Resumo e conclusão

    Um objeto DatabaseMetaData é obtida através do objeto Connection e oferecerá recursos de recuperação de metadados da base de dados e da sua conexão atual, pode ser utilizada por exemplo para verificar quais os schemas(usuários) de uma base de dados, se a conexão atual possui suporte a um determinado nível de isolamente de transações, ou até mesmo qual a versão do Driver JDBC. Um objeto ResultSetMetaData pode ser obtida através de um ResultSet previamente criado ou através das classes PreparedStatement e CallableStatement, lhe possibilitando a recuperação de metadados sobre as colunas da cláusula SQL atual, como a quantidade de colunas, nome e tipos das mesmas. Um objeto ParameterMetaData é obtida através de um PreparedStatement, e permite que você possa recuperar metadados sobre os parâmetros usados em clausulas SQL. Com essas três classes é possível recuperar informações dinamicamente de uma base de dados. Alguns desenvolvedores utilizam constantemente essas três classes para criarem seu próprio framework de persistência de dados.

  4.  
    Deixe um comentário

    Publicado por em 23/11/2009 em Estudos Java

     

    Splash Screen

    Introdução

    Neste simples artigo iremos ver como criar uma tela Splash. Um splash é aquela imagem que geralmente aparece enquanto o programa principal esta sendo carregado na memória, sendo bastante útil para mostrar ao usuário que o sistema não esta travado, muito pelo contrário. Além de tudo, uma tela Splash deixa seu programa com uma cara mais profissional.

    Splash it!

    Não há misterio em fazer tal tela, o funcionamento baseia-se na idéia de mostrar uma imagem em um JFrame enquanto a JVM encarrega-se de abrir a tela principal do programa. A classe que implementa a tela de Splash do nosso exemplo chama-se "Splash", e é declarada da seguinte forma:

     

    1. public class Splash extends Window 

    public class Splash extends Window
    Temos apenas 5 propriedades, que são:

     

    1. // Mensagem a ser mostrada junto com a imagem
    2. private final String message = "Splash Screen"; 
    3.  
    4. // Imagem que ira aparecer no Splash
    5. private final String imgName = "splash_guj.jpg"; 
    6. Image splashImage; 
    7. Toolkit toolkit; 
    8. private static Splash splash; 

    // Mensagem a ser mostrada junto com a imagem private final String message = "Splash Screen"; // Imagem que ira aparecer no Splash private final String imgName = "splash_guj.jpg"; Image splashImage; Toolkit toolkit; private static Splash splash;
    Note que temos uma propriedade chamada da própria classe Splash, que é utilizada para garantir que apenas uma instância estará na memória por ClassLoader(Singleton). O método que executa o trabalho grosso é o initSplash, que é mostrado abaixo:

     

    1. private void initSplash() { 
    2. // Carrega a imagem na memoria
    3.     MediaTracker media = new MediaTracker(this); 
    4.     splashImage = toolkit.getImage(imgName); 
    5.  
    6. if (splashImage != null) { 
    7.         media.addImage(splashImage, 0); 
    8.  
    9. try { 
    10.             media.waitForID(0); 
    11.         } 
    12. catch (InterruptedException ie) {} 
    13.     } 
    14.  
    15. // Configura o tamanho do splash e a posicao na tela
    16.     setSize(splashImage.getWidth(this), splashImage.getHeight(this)); 
    17.  
    18.     Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); 
    19.     Dimension size = getSize(); 
    20.  
    21. if (size.width > screenSize.width) 
    22.         size.width = screenSize.width; 
    23.  
    24. if (size.height > screenSize.height) 
    25.         size.height = screenSize.height; 
    26.  
    27.     setLocation((screenSize.width – size.width) / 2, (screenSize.height – size.height) / 2); 
    28.     setVisible(true);        

    private void initSplash() { // Carrega a imagem na memoria MediaTracker media = new MediaTracker(this); splashImage = toolkit.getImage(imgName); if (splashImage != null) { media.addImage(splashImage, 0); try { media.waitForID(0); } catch (InterruptedException ie) {} } // Configura o tamanho do splash e a posicao na tela setSize(splashImage.getWidth(this), splashImage.getHeight(this)); Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); Dimension size = getSize(); if (size.width > screenSize.width) size.width = screenSize.width; if (size.height > screenSize.height) size.height = screenSize.height; setLocation((screenSize.width – size.width) / 2, (screenSize.height – size.height) / 2); setVisible(true); }
    Para desenhar a imagem na tela precisamos implementar o método paint, como mostrado abaixo:

     

    1. public void paint(Graphics g) { 
    2. // Apenas desenha a nossa mensagem em cima da imagem
    3.     g.drawImage(splashImage, 0, 0, getBackground(), this); 
    4.     g.setFont(new Font("Arial", Font.BOLD, 26)); 
    5.     g.drawString(message, (int)(splashImage.getWidth(this) / 2) – 80, 30); 

    public void paint(Graphics g) { // Apenas desenha a nossa mensagem em cima da imagem g.drawImage(splashImage, 0, 0, getBackground(), this); g.setFont(new Font("Arial", Font.BOLD, 26)); g.drawString(message, (int)(splashImage.getWidth(this) / 2) – 80, 30); }
    O código fonte completo você encontra no arquivo que acompanha este tutorial.

    Classe para simular o programa real

    Com a classe que irá mostrar o Splash pronta, vamos fazer uma outra classe para "simular" um programa real, pesado. Para fazer tal ação simplemente é colocado um laço for() no construtor da classe, assim é possível analisar o funcionamento do Splash. Se fosse um Thread.sleep(), estaríamos perdendo o tempo que a splash fica aberta! O código é o seguinte:

     

    1. class Botoes extends JFrame { 
    2.     JButton botao; 
    3.     JFrame frame; 
    4.     JPanel panel; 
    5.  
    6. /**
    7.      * Construtor da aplicacao principal.
    8.      * Simula um load demorado com um loop, para mostrar que
    9.      * a tela Splash realmente aparece enquanto a aplicacao
    10.      * principal eh carregada.
    11.      * */
    12. public Botoes() { 
    13. for (int i = 0; i < 50000; i++) 
    14.             System.out.println(i); 
    15.  
    16.         frame = new JFrame("Botoes"); 
    17.         panel = new JPanel(); 
    18.  
    19.         panel.setLayout(new GridLayout(4, 1)); 
    20.  
    21.         botao = new JButton("Aplicação inicializada"); 
    22.         botao.addActionListener(new ActionListener() { 
    23. public void actionPerformed(ActionEvent e) { 
    24.                 System.exit(0); 
    25.             } 
    26.         }); 
    27.  
    28.         panel.add(botao); 
    29.  
    30.         frame.getContentPane().add(panel, BorderLayout.CENTER); 
    31.         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    32.     } 
    33.  
    34. public void initApplication() { 
    35.         frame.pack(); 
    36.         frame.setVisible(true); 
    37.  
    38.         Splash.getInstance().finish(); 
    39.     } 

    class Botoes extends JFrame { JButton botao; JFrame frame; JPanel panel; /** * Construtor da aplicacao principal. * Simula um load demorado com um loop, para mostrar que * a tela Splash realmente aparece enquanto a aplicacao * principal eh carregada. * */ public Botoes() { for (int i = 0; i < 50000; i++) System.out.println(i); frame = new JFrame("Botoes"); panel = new JPanel(); panel.setLayout(new GridLayout(4, 1)); botao = new JButton("Aplicação inicializada"); botao.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { System.exit(0); } }); panel.add(botao); frame.getContentPane().add(panel, BorderLayout.CENTER); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } public void initApplication() { frame.pack(); frame.setVisible(true); Splash.getInstance().finish(); } }

    Finalizando

    Construindo a classe que implementa main(): Para testar nossa tela Splash basta fazer um programinha extremamente simples, como o mostrado abaixo:

     

    1. public class TestSplash { 
    2. public static void main(String[] args) {         
    3. // Faz o splash aparecer na tela
    4.         Splash.getInstance().openSplash(); 
    5.  
    6. // Chama a nossa aplicacao principal
    7.         Botoes b = new Botoes(); 
    8.         b.initApplication(); 
    9.     } 

    public class TestSplash { public static void main(String[] args) { // Faz o splash aparecer na tela Splash.getInstance().openSplash(); // Chama a nossa aplicacao principal Botoes b = new Botoes(); b.initApplication(); } }
    Pronto, agora basta compilar e visualizar o exemplo. Se tudo ocorrer direito, o Splash com o logo do GUJ irá aparecer na tela do monitor, e prestando atenção na tela do terminal você irá ver um contador sendo incrementado. Este contador é o que foi criado na classe Botao. O Splash irá sumir da tela assim que o contador terminar. É isso, um exemplo bastante simples mas que faz algo bem legal. Com algumas linhas de código a mais da para fazer coisas bem legais, como mostrar o status do programa sendo carregado direto na tela Splash, por exemplo. Claro que ainda existem milhares de outras abordagens para uma SplashScreen ser criada!

     
    Deixe um comentário

    Publicado por em 23/11/2009 em Estudos Java

     

    Retirando o SQL do seu código Java

    Introdução

    Uma das boas práticas de programação, não só em java, é diminuir ao máximo o uso de Strings literais no seu código fonte, técnica conhecida como "hardcoding". Um "antipadrão" de programação. Porque isto é ruim? Bem, primeiro que você fica dependendo de recompilar o código se precisar mudar alguma coisa. Segundo que fica difícil você achar um mispelling (erro na hora de digitar) de uma String literal, e terceiro que é terrível ler Strings e magic numbers no código de uma pessoa. O que é Magic Number?

    1. if (this.codigo == 47) { 
    2. // faca algo

    if (this.codigo == 47) { // faca algo }
    O número 47 não representa nada para ninguém, e esse código fica difícil de ser lido. Imagine agora com uma constante:

     

    1. if (this.codigo == DATABASE_ACCESS_ERROR) { 
    2. // faca algo

    if (this.codigo == DATABASE_ACCESS_ERROR) { // faca algo }
    O mesmo acontece para Strings literais. Claro que em java você utilizaria Exceptions ao invés de código de erros, isto foi apenas um exemplo. Neste tutorial, aprenderemos a tirar as strings SQLs "hardcodadas" no seu .java, de maneira elegante e eficiente. Para isto, é necessário você ter um conhecimento básico de JDBC e conhecer a java.util.Properties (ou leia a API!). Uma vantagem enorme de retirar o seu SQL do .java, é que assim você torna a sua aplicação quase que indepedente de banco de dados (se você tomar bastante cuidado, vira 100% independente). Voce pode mudar em um arquivo de configuracao as SQLs, por exemplo, de TOP para LIMITm diferença clássica entre alguns banco de dados!

    PreparedStatement

    java.sql.PreparedStatement é uma interface que extende a interface Statement. A grande maioria dos drivers JDBCs atuais suportam a utilização desta interface. O que ela faz? Bem, vamos dar um exemplo concreto, para irmos explicando:

     

    1. Connection conn = DriverManager.getConnection("jdbc:banco…"); 
    2.  
    3. PreparedStatement pstmt = con.prepareStatement("UPDATE EMPLOYEES SET SALARY = ? WHERE ID = ?"); 
    4.  
    5. pstmt.setBigDecimal(1, 153833.00) 
    6. pstmt.setInt(2, 110592) 

    Connection conn = DriverManager.getConnection("jdbc:banco…"); PreparedStatement pstmt = con.prepareStatement("UPDATE EMPLOYEES SET SALARY = ? WHERE ID = ?"); pstmt.setBigDecimal(1, 153833.00) pstmt.setInt(2, 110592)
    Este é o exemplo que está na própria API. O que ele faz? Primeiro ele pega uma conexão com o banco de dados, exatamente como sempre fizemos. Depois, ele devolve um PreparedStatement a partir de um SQL meio estranho: ele possui pontos de interrogação onde queremos reutilizar a SQL query. Para substituir esses pontos de interrogação, basta usar um dos vários métodos setters que a interface PreparedStatement lhe oferece. Lembre-se que o setter recebe um inteiro, indicando qual ponto de interrogação será utilizado: o primeiro vale 1, diferente de indices de arrays que começam com 0 em java. Chamado o setter, o driver JDBC vai dar um jeito de traduzir aquele objeto/valor primitivo para dentro da SQL. Se você colocar uma String, não precisa por as aspas!!! Porque? Pois o driver JDBC cuida disso:

     

    1. PreparedStatement pstmt = con.prepareStatement("select * from usuario where name = ?"); 
    2.  
    3. // não precisa de escape no ‘
    4. pstmt.setString(1,"Joãozinho D’a Silva"); 

    PreparedStatement pstmt = con.prepareStatement("select * from usuario where name = ?"); // não precisa de escape no ‘ pstmt.setString(1,"Joãozinho D’a Silva");
    Uma maneira muito comum de utilizar o PreparedStatement, é usar o método setObject. Este método vai fazer vários instanceof e descobrir como deve colocar esse valor na sua SQL. Caso ele não descubra, ele vai chamar o toString deste método. Continuando o primeiro caso:

     

    1. pstmt.setObject(1, new Long(5000)); 
    2. pstmt.setObject(2, new Integet(333)); 

    pstmt.setObject(1, new Long(5000)); pstmt.setObject(2, new Integet(333));
    Se você tentar setar um índice que não exista vai receber uma RuntimeException. Por exemplo, no nosso caso, setObject(3,…) iria resultar em uma RuntimeException, indicando que não existe o 3o ponto de interrogação na SQL dada! Para executar o PreparedStatement, é idêntnico ao Statement. Lembre-se de "setar" tudo antes de executá-lo, ou você receberá uma exceção:

     

    1. ResultSet rs = pstmt.executeQuery(); // sem passar argumento!

    ResultSet rs = pstmt.executeQuery(); // sem passar argumento!
    O que mais o PreparedStatement é responsável por fazer?

  5. Fazer o escape das aspas, aspas simples, e do próprio caractere de escape – isso é muito útil;
  6. Traduzir muitos objetos para o formato String correspondente com o do banco de dados, como o java.util.Date por exemplo, e o java.io.InputStream, que eu considero o mais útil de todos: fica muito fácil utilizar um campo Blob com um PreparedStatement. Antes que alguém pergunte, o driver de JDBC para o mysql tem sim, suporte a PreparedStatement. Aliás, o GUJ usa e abusa deste recurso, inclusive para guardar as imagens no banco de dados em BLOBs. Aqui você já tem uma idéia legal de como aproveitar o PreparedStatement, mas sugiro que você conheça a api dele, clicando aqui.

    Arquivo de Configuração

    Após aprendermos a usar o PreparedStatement, vamos fazer algo para retira-los do seu .java. Para isso, vamos passar todas as Strings que representam uma SQL para um arquivo de Properties, algo do tipo:

     

    1. usuario.selectByName=select * from usuario where name = ? 
    2. usuario.selectByEmail=select * from usuario where email = ? 

    usuario.selectByName=select * from usuario where name = ? usuario.selectByEmail=select * from usuario where email = ?
    Então, ao invés de criarmos o PreparedStatement a partir de um String literal, nós pegamos ele a partir deste arquivo Properties. Um esboço:

     

    1. Properties queries = new Properties(); 
    2. queries.load("arquivoMysql.txt"); 

    Properties queries = new Properties(); queries.load("arquivoMysql.txt");
    Na hora de criar um PreparedStatement, você faz assim:

     

    1. PreparedStatement ps = connection.prepareStatement(queries.getProperty(USUARIO_SELECT_BY_NAME)); 

    PreparedStatement ps = connection.prepareStatement(queries.getProperty(USUARIO_SELECT_BY_NAME));
    Onde USUARIO_SELECT_BY_NAME é uma constante: uma String static final e pública. Porque isso? evitar o hardcoding e erros de execução. Com isso, você não terá mais nenhum SQL dentro do seu .java, o que é um grande passo. Vamos melhorar nosso esboço de como controlar essa properties que contém os SQLs.

    O Singleton que controla tudo

    Vamos criar aqui uma classe (esboço novamente) para controlar essa properties que tem as SQLs. Não podemos ficar lendo do arquivo texto toda vez que pegarmos uma SQL, precisamos de uma classe (instância dela) para fazer isso. Você não precisa saber o que é um Singleton. É basicamente uma solução para você não fazer uma classe que tenha tudo static, desta maneira, você perderia a orientação a objetos.

     

    1. public class QueryManager { 
    2.  
    3. protected Properties queries; 
    4.  
    5. // nao deveria estar hardcodado:
    6. protected static queryManager = new Querymanager("arquivoMysql.txt"); 
    7.  
    8. private QueryManager(String arquivo) { 
    9.         queries = new Properties(); 
    10. // le as sqls e guarda!
    11.         queries.load(new FileInputStream(arquivo)); 
    12.     } 
    13.  
    14.     … 
    15.  

    public class QueryManager { protected Properties queries; // nao deveria estar hardcodado: protected static queryManager = new Querymanager("arquivoMysql.txt"); private QueryManager(String arquivo) { queries = new Properties(); // le as sqls e guarda! queries.load(new FileInputStream(arquivo)); } … }
    Até aqui temos o padrão singleton implementado, mas vamos adicionar o método que retorna um PreparedStatement, dado uma conexão e o nome do statement que você quer!

     

    1. public PreparedStatement getPreparedStatement(Connection conn, String queryName) throws SQLException { 
    2.     String query = this.queries.getProperty(queryname); 
    3. return conn.prepareStatement(query); 

    public PreparedStatement getPreparedStatement(Connection conn, String queryName) throws SQLException { String query = this.queries.getProperty(queryname); return conn.prepareStatement(query); }
    Cuidado: este método pode dar NullPointerException no caso da query requerida não existir no arquivo de configuração! Para utilizar esta classe:

     

    1. QueryManager manager = QueryManager.getQueryManager(); 
    2.  
    3. PreparedStatement ps = manager.getPreparedStatement(conn, USUARIO_SELECT_BY_NAME); 
    4. ps.setString(1, "Joaozinho"); // poderia ser setObject, recomendo!
    5. ResultSet rs = ps.executeQuery(); 

    QueryManager manager = QueryManager.getQueryManager(); PreparedStatement ps = manager.getPreparedStatement(conn, USUARIO_SELECT_BY_NAME); ps.setString(1, "Joaozinho"); // poderia ser setObject, recomendo! ResultSet rs = ps.executeQuery();
    Simples não? Não tenha medo do singleton, a única coisa que ele faz é impedir que exista mais de uma instância desta classe por ClassLoader.

    Conclusão

    Este tutorial foi realizado devido a muitos pedidos de como retirar o SQL do codigo java. Você pode refinar o processo, utilizando XML no caso que você tenha uma hierarquia entre as SQLs. O problema seria escrever um parser apenas para este arquivo de configurações. Você ainda pode melhorar essa solução: utilizando alguma biblioteca/ferramenta que possibilite o "mapeamento objeto relacional". Usar uma ConnectioPool também é muito útil! Espero que tenha ficado claro a melhoria que você ganha a partir do momento que para de lidar com literais: maior reuso do código, melhor leitura, maior adaptação e facilidade de reescrita. E é claro: quem não gosta de um arquivinho de configurações :).

  7.  
    Deixe um comentário

    Publicado por em 23/11/2009 em Estudos Java

     

    Introdução ao JDBC

     

    Introdução

    Com este tutorial, você aprenderá a utilizar o JDBC, fazendo uma conexão com o banco de dados. Apesar de ser bem básico, e fazer apenas um SELECT, iremos explicar direitinho como funciona o JDBC, para você não ter de decorar "receitas de bolo". Vamos utilizar o MySQL, mas você pode facilmente usar qualquer banco de dados de sua preferência.

    O pacote java.sql

    Olhando para a API do pacote, você logo vai se perguntar: Porquê as classes do java.sql são, em sua grande maioria, apenas interfaces? Desta maneira, a implementação dessas classes fica por conta de alguém que entenda de determina banco de dados. Por exemplo, se temos o MySQL, alguém que entenda do MySQL implementa as classes do java.sql, desta forma, nós podemos fazer conexão com o MySQL através destas classes. Ao contrário de linguagens como php, o java não implementa esses drivers, desta maneira, novos drivers vão aparecendo na medida em que novos bancos de dados e novas versões deles vão aparecendo, o que seria um caos para a SUN ter de fazer, além de provavelmente não utilizar o melhor potencial do banco de dados.

    Um pouco de código

    Então, onde configuramos qual driver a minha aplicação deve usar? Na verdade, você pode ter vários drivers ao mesmo tempo, e a utilização deles vai de acordo com qual String de conexão você utilizar. O driver é um jar (se for um driver puro java), e você deve te-lo em seu classpath, caso contrário não conseguirá utilizá-lo. Se preferir, coloque o driver no classpath na hora de chamar o java, atraves da linha de comando, por exemplo:

     

    1. java -classpath diretorio/meudriver.jar MinhaClasse 

    java -classpath diretorio/meudriver.jar MinhaClasse
    Você pode pegar o driver do mysql aqui. Porém, precisamos antes "carregar" o driver, de tal maneira que o Java saiba que ele existe, e possa usá-lo se necessário. Normalmente, os livros explicam isto de forma muito básica, e não entram em detalhes, já que o código que carrega o driver é do tipo:

     

    1. Class.forName("com.mysql.jdbc.Driver"); 

    Class.forName("com.mysql.jdbc.Driver");
    Mas o que acontece realmente aqui? Quando você utiliza o método estático Class.forName(), o Class Loader tenta inicializar esta classe. Esta classe (que é o nosso driver jdbc) possui um bloco inicializador estático (não se preocupe caso você não conheça este recurso), que irá registrar essa classe como um driver JDBC, avisando o java.sql.DriverManager, pelo método registerDriver. Obs: Existem outras maneiras de carregar o driver, como por linha de comando (bootstrap). Agora que o driver já está registrado, podemos abrir uma conexão com o banco de dados, passando uma String de conexão.

     

    1. Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/BANCO_DE_DADOS?user=root&password=root"); 

    Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/BANCO_DE_DADOS?user=root&password=root");
    Desta vez, o java.sql.DriverManager vai perguntar para cada Driver registrado, se ele aceita a String de conexão em questão. Se algum deles aceita esta String, a conexão é aberta (pelo Driver), e retornada. Caso contrário, uma exceção é lançada. Pela própria String de conexão, você pode passar muitos outros parâmetros (além de login, senha e nome do banco de dados, como neste caso), a maioria de interesse do Driver, como por exemplo saber se aquela conexão deve estar em modo de auto reconexão caso ela caia, e muitos outros. Este tipo de informação está na documentação do seu driver.

    Um simples SELECT

    Vamos agora fazer um SELECT, e pegar os dados que este SELECT devolver, imprimindo-os. Lembre-se que você deve adaptar a String de conexão e o nome do bancod e dados, tabela e campos para um que você já tenha em sua máquina, claro.

     

    1. Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/BANCO_DE_DADOS?user=root&password=root"); 
    2. Statement stm = conn.createStatement(); 
    3. ResultSet rs = stm.executeQuery("SELECT coluna1, coluna2, coluna3 FROM tabela"); 

    Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/BANCO_DE_DADOS?user=root&password=root"); Statement stm = conn.createStatement(); ResultSet rs = stm.executeQuery("SELECT coluna1, coluna2, coluna3 FROM tabela");
    O método Connection.createStatement() te devolve um objeto java.sql.Statement, que representa uma simples Query ou comando. Nós utilizamos depois o Statement.executeQuery(), que devolve um java.sql.ResultSet com o resultado. Caso a quey fosse algo que não retornasse nada, tipo um INSERT ou UPDATE, você deve utilizar o Statement.executeUpdate(). Agora temos um java.sql.ResultSet, que contém o resultado da nossa Query. Vamos iterar sobre ele:

     

    1. while (rs.next()) { 
    2.     String coluna1 = rs.getString("coluna1"); 
    3. int coluna2 = rs.getInt("coluna2"); 
    4.     Date coluna3 = rs.getDate("coluna3"); 

    while (rs.next()) { String coluna1 = rs.getString("coluna1"); int coluna2 = rs.getInt("coluna2"); Date coluna3 = rs.getDate("coluna3"); }
    Muito intuitivo não? Repare que o java.sql.ResultSet possui uma série de métodos para que você possa pegar o valor da coluna já no tipo desejado, como String, int, Date, etc…

    Considerações finais

    Aqui utilizamos código SQL dentro das classes Java, isto é um péssimo hábito. O interessante é ter as queries dentro de um arquivo de configuração, como um XML ou um arquivo de properties. Desta maneira, caso você mude de banco de dados, pode facilmente mudar as queries que não são compatíveis. Além disso, apresentamos aqui apenas o java.sql.Statement, mas é altamente recomendável o uso do java.sql.PreparedStatement, onde você pode reutilizar bastante os statements e o seu driver JDBC pode ajudar bastante na hora de você ter de fazer coisas como escape de Strings (colocar \ na frente das aspas de uma String, por exemplo). Fica aqui a recomendação da leitura da api desta classe.

     
    Deixe um comentário

    Publicado por em 23/11/2009 em Estudos Java