Access

Java, acessando banco de dados MS-Access em Windows 64bits

Posted on fevereiro 2, 2013. Filed under: Access, Java | Tags:, , , |

Introdução

Neste artigo vamos aprender como acessar um banco de dados MS-Access pelo Java. No caso, estaremos com o Windows instalado em uma arquitetura 64bits. Mesmo estando na arquitetura 64bits, o Windows ainda distribui os drivers ODBC do MS-Access em arquitetura 32bits (Pelo menos no Windows 7). Portanto, para que o Java possa usar o driver ODBC do Ms-Access, teremos que rodar o Java em uma JVM de arquitetura 32bits.

Configurando o ODBC

O primeiro passo é configurar um data source no administrador de fonte de dados ODBC do Windows. Como estamos usando o Windows 64bits, abra o odbcad32.exe no seguitne caminho:
C:\Windows\SysWOW64\odbcad32.exe

PS: Não acesse o odbcad32.exe dentro do diretório System32, pois não funcionará corretamente devido a arquitetura do Windows ser 64bits.

Após aberto o gerenciador de fonte de dados, clique na aba “Fonte de dados do Sistema”, em seguida, clique no botão Adicionar, para adicionar uma nova fonte de dados.

ScreenShot048

Selecione o Microsoft Access Driver como tipo de driver para fonte de dados. No meu caso, preciso conectar em um banco de dados MS-Access com extensão .accdb:

ScreenShot049

Na próxima tela informe o nome da fonte de dados. Esse nome será usado para identificar o banco de dados na hora do acesso (Vamos usar esse nome em nosso programa Java).

Clique no botão Selecionar e escolha o banco de dados MS-Access. (No meu caso é um arquivo com extensão .accdb) e clicar em OK:

ScreenShot050

Criando o aplicativo Java

O código abaixo é um exemplo de como fazer o Java conectar em um banco de dados MS-Access. Verificar no próprio código, os comentários para qualquer dúvida.

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;


/**
 * Classe responsável por gerenciar conexões com banco de dados MS-Access
 * @author Douglas.Pasqua
 *
 */
public class AccessConnect {
	private static final String username = "";
	private static final String password = "";
	private static final String DSN = "DatabaseUsuarios"; // nome da fonte de dados
	private static final String driver = "sun.jdbc.odbc.JdbcOdbcDriver"; // driver usado
	private static Connection conn = null;
	        
	/**
	 *  retorna uma conexão com o banco de dados Access. 
	 *  Utiliza o Design Pattern Singleton
	 */ 
	public static Connection getConnection() throws Exception {
	    if(conn == null) {
	        String url = "jdbc:odbc:" + DSN;
	        Class.forName(driver);
	        conn = DriverManager.getConnection(url, username, password);
	    }
	    return conn;
	}
	
	/**
	 * Fecha a conexão com o Banco de dados access
	 * Chamar esse método ao sair da aplicação
	 */
	 public static void close() {
        if(conn != null) {
            try {
                conn.close();
            } catch (SQLException ex) {
                ex.printStackTrace();
            } finally {
                conn = null;
            }
        }
    }
	
	/**
	 * Exemplo de teste da classe de conexão com o 
	 * Access
	 */
	public static void main(String[] args) {
		try {
			// inicilizando a conexão
			Connection conn = AccessConnect.getConnection();

			Statement st = conn.createStatement();
            ResultSet rs = st.executeQuery("SELECT nome FROM usuario"); // temos uma tabela usuario com o campo nome
            while(rs.next()) {
            	String nome = rs.getString("nome");
                System.out.println("Nome: " + nome);
            }
            
            // fechando a conexão
			AccessConnect.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

Ao executar o código acima, caso esteja em uma arquitetura 64bits, provavelmente a jvm usada também estará em 64bits, você obterá a seguinte Exception:

java.sql.SQLException: [Microsoft][ODBC Driver Manager] O DSN especificado contém uma incompatibilidade de arquiteturas entre o Driver e o Aplicativo

Como os drivers nativos do MS-Access no windows são 32bits e você esta executando o código em uma virtual machine do java em 64bits, será gerado o Exception acima. Para que você possa rodar o aplicativo sem erros, é necessário instalar o JRE do java para 32bits.

Instalando o JRE para 32bits

Para instalar o JRE versão 32bits para windows, acesse o link abaixo primeiramente:
http://www.oracle.com/technetwork/java/javase/downloads/index.html

Clique no download de JRE na versão desejada. Na próxima tela escolha a versão do java para x86. Exemplo:
jre-7u11-windows-i586.exe

Não se preocupe caso já tenha outra versão do java instalada. Não haverá conflitos. Após a instalação do JRE para 32bits, o próximo passo é executar o seu aplicativo java com essa nova jvm recém-instalada. Veremos abaixo como fazer através de linha de comando, Netbeans e Eclipse.

Executando através de linha de comando

Executar o java de 32bits através da linha de comando é simples. Basta usar o comando java do JRE de 32bits recém-instalado.
(Lembre-se que o importante é executar o bytecode do java em arquitetura 32bits. O compilador do java, javac, pode estar em outra arquitetura)

"C:\Program Files (x86)\Java\jre7\bin\java" -cp . AccessConnect

Executando através do Netbeans

No diretório bin\ da instalação do Netbeans tem dois executáveis: Netbeans.exe e Netbeans64.exe ! Inicie o Netbeans usando o executável Netbeans.exe. Desas forma, ele usará uma jvm em 32bits para executar os arquivos java de dentro do IDE Netbeans.

ScreenShot051

Executando através do Eclipse

Primeiro, vamos configurar a JRE de 32bits instalada no processo anterior. O Eclipse permite que você configure quantas JRE forem necessárias. Depois, nas propriedades do projeto, você escolhe qual JRE deseja usar.

No Eclipse, clique em “Window -> Preferences” e depois no botão “Add”:

ScreenShot052

Na próxima tela, escolha “Standard VM” e clique em “Next”:

ScreenShot053

Na próxima tela, informe o caminho do JRE 32bits. Caso necessário, altere o campo JRE Name para não conflitar com outro JRE já instalado:

ScreenShot054

Para continuar clique em “Finish”. Depois na tela de “Preferences”, clique em Ok.

Em seguida, clique com o botão direito do mouse em cima do projeto que contém a aplicação de acesso ao Ms-Access que você deseja testar.
Vá em “Build Path -> Configure Build path”!

Na tela “Java Build Path”, clique na aba “Libraries”!

Clique na linha “JRE System Library” e em “Edit” para poder escolher o JRE que acabamos de configurar. Irá abrir uma nova tela para selecionar o JRE usado para fazer o build do projeto. No campo “Alternate JRE”, escolha a JRE que acabamos de configurar. Clique em “Finish”:

ScreenShot055

Pronto, agora você já pode rodar sua aplicação que conecta no MS-Access pelo Java.

Ler Post Completo | Make a Comment ( 8 so far )

Java, Remove OLE headers from images stored as OLE Objects in access database

Posted on janeiro 24, 2013. Filed under: Access, Java | Tags:, , |

If you are using Java to access a MS Access database, and need to retrieve images stored in fields of type OLE Object, then this post can help you. When you insert images into OLE Object fields directly using the MS Access client, and you need to retrieve this image later to use in a desktop application or a web site, you will have a problem. The problem, is that the MS Access insert an OLE Header in the image file registered in database. So you will need to remove the OLE Header to use the image out of the Ms Access. The code below acomplishes this task.

This post is based on:
http://blogs.msdn.com/b/pranab/archive/2008/07/15/removing-ole-header-from-images-stored-in-ms-access-db-as-ole-object.aspx

I just ported the code to Java language.

The code:

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

/**
 * Class to remove OLE Header from images stored as OLE Object
 * @author Douglas.Pasqua
 */
public class OLEImage {
    
    // Map to store the initial block of different images formats
    private Map<String, String> imagesBeginBlock;

    public OLEImage() {
        // inicialize
        imagesBeginBlock = new HashMap<String, String>();
        imagesBeginBlock.put("JPEG", "\u00FF\u00D8\u00FF"); // JPEG
        imagesBeginBlock.put("PNG", "\u0089PNG\r\n\u001a\n"); // PNG
        imagesBeginBlock.put("GIF", "GIF8"); // GIF
        imagesBeginBlock.put("TIFF", "II*\u0000"); // TIFF
        imagesBeginBlock.put("BMP", "BM"); // BMP
    }
   
    public byte[] getByteImgFromOLEInputStream(InputStream input, String imageFormat) {
        // get begin block identifier using imageFormat parameter
        String beginBlock = imagesBeginBlock.get(imageFormat);
        if(beginBlock == null) {
            throw new RuntimeException("Unsupported image format parameter value.");
        }
        
        try {
            byte[] b = toByteArray(input);
            String str = new String(b, "ISO-8859-1");
            
            // identifying the initial position of the image 
            int index = str.indexOf(beginBlock);
            if(index == -1) {
                throw new RuntimeException("Unable to determine image format.");
            }
            
            // removing the OLE Header 
            byte[] buffer = new byte[b.length - index];
            for(int i = 0, a = index; a < b.length; i++, a++) {
                buffer[i] = b[a];
            }
            return buffer;
            
        } catch(IOException e) {
            e.printStackTrace();
        } 
        
        return null;
    }
    
    /**
     * Convert InputStream object to array of bytes
     * @throws IOException 
     */
    public byte[] toByteArray(InputStream is) throws IOException {
        int len;
        int size = 1024;
        byte[] buf;

        if (is instanceof ByteArrayInputStream) {
            size = is.available();
            buf = new byte[size];
            len = is.read(buf, 0, size);
        } else {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            buf = new byte[size];
            while ((len = is.read(buf, 0, size)) != -1) {
                bos.write(buf, 0, len);
            }
            buf = bos.toByteArray();
        }
        return buf;
    }
}

Examples of Use

Using with JPEG, PNG and GIF images on Desktop Applications

Java has native support for JPG, PNG and GIF images. So theses images format will work well with ImageIcon class:

// the class to remove de OLE Headers from OLE Objects
OLEImage oleImage = new OLEImage();

// get OLE object field from access database
// ...

// using with GIF format
InputStream input = rs.getBinaryStream("oleGIF");
byte buffer[] = oleImage.getByteImgFromOLEInputStream(input, "GIF");
ImageIcon icon = new ImageIcon(buffer);

// using with JPEG format
InputStream input = rs.getBinaryStream("oleJPEG");
byte buffer[] = oleImage.getByteImgFromOLEInputStream(input, "JPEG");
ImageIcon icon = new ImageIcon(buffer);

// using with PNG format
InputStream input = rs.getBinaryStream("olePNG");
byte buffer[] = oleImage.getByteImgFromOLEInputStream(input, "PNG");
ImageIcon icon = new ImageIcon(buffer);

Using TIFF and BMP Images on Desktop Applications

Our OLEImage class supports removing OLE Headers for TIFF and BMP images format too. But java doesn’t support these image formats natively. So, you can’t use these formats directly with ImageIcon.

If you are developing for desktop, you will need a alternative method to support these formats. The following links can help you with this task:

http://stackoverflow.com/questions/593830/display-bmp-in-jlabel
http://stackoverflow.com/questions/1567398/showing-tiff-images-in-java
http://stackoverflow.com/questions/9634472/how-to-set-tif-image-to-imageicon-in-java

Using all Image Formats on Web Applications

You are free to use any image format when working in web enviroment. (If you need to send these images from Access database to client browser).

Ler Post Completo | Make a Comment ( None so far )

Liked it here?
Why not try sites on the blogroll...

%d blogueiros gostam disto: