Problema com criação de Banco de Dados com h2

11 respostas
D

Olá a todos.

Pessoal, estou tendo problemas com a criação de um banco de dados em JDBC utilizando o h2 database.

Por exemplo, consigo criar um Banco de Dados usando MySQL através de minha aplicação, como segue:

Na minha classe getConnection tento realizar a conexão da forma convencional:

try{

Connection conexao = DriverManager.getConnection(url1, usuario, senha);

}

onde > url1 = “jdbc:mysql://localhost:3306//meuBD”;

Caso o Banco de Dados não exista tento o seguinte:

catch{

try{
Connection conexao = DriverManager.getConnection(url2 + "user=" + usuario + "&" + "password=" + senha);`
        Statement stmt = conexao.createStatement();
        stmt.executeUpdate("CREATE DATABASE IF NOT EXISTS meuBD");
  }

}

onde > url2 = “jdbc:mysql://localhost:3306?”;


Porém, tentando fazer o mesmo com h2 não consigo o mesmo resultado.

Tive problemas na primeira parte em que se tenta acessar o BD, pois por padrão é criado um novo banco de dados vazio quando a base de dados especificada na URL do h2 não existe. Mas já resolvi passando a url da seguinte forma:

url1 = “jdbc:h2:/~/meuBD;IFEXISTS=TRUE”;

O problema é na segunda parte, quando tento criar o BD:

catch{

try{
   Connection conexao = DriverManager.getConnection(url2 + "user=" + usuario + "&" + "password=" + senha);
   Statement stmt = conexao.createStatement();
   stmt.executeUpdate("CREATE SCHEMA IF NOT EXISTS meuBD");
}
  }

Tentei passar a url2 como > “jdbc:h2:/~/?”, semelhante ao código do MySQL, mas não deu certo.

Como posso criar o BD direto no software usando o h2?

Desde já agradeço a quem puder ajudar.

11 Respostas

SandroSoftwares

veja o código em http://sandrosoftwares.com.br/codigo.html

SandroSoftwares

quando estou iniciando o meu aplicativo pela primeira vez dou um comando show tables,
se não retornar nenhuma tabela crio as tabelas dinamicamente…
se retornar alguma tabela eu as acesso…

o método para verificar que uso é esse:

public int verificaSeExisteBanco() throws SQLException {

String sql = Show Tables;

PreparedStatement stmt = conexao.prepareStatement(sql); // para guardar a conexão sem precisar fazer outra

ResultSet rs = stmt.executeQuery();

int a = 0;

while (rs.next()) {

++a;

}
return a;

}
SandroSoftwares

para cria-las dinamicamente uso o código (exemplo):

String sql = " DROP TABLE IF EXISTS usuarios;"
+ " CREATE TABLE usuarios ("
+ " idUsuario INTEGER unsigned NOT NULL AUTO_INCREMENT,"
+ " email text,"
+ " senha text,"
+ " PRIMARY KEY (idUsuario)"
+ " );";

PreparedStatement stmt = conexao.prepareStatement(sql);

stmt.execute();

stmt.close();

JOptionPane.showMessageDialog(null, Parabéns por adquirir este Software!!!);
D

Antes de mais nada, obrigado pela solicitude! :smiley:

Minha aplicação é standalone e eu gostaria de utilizar o h2 como BD embarcado. Acho que faltou dizer isto no início. Oo

A ideia seria criar o schema meuBD a partir do meu aplicativo, sem a necessidade de distribuí-lo junto com o JAR.

Vi em outro tópico que era possível retornar uma conexão em MySQL mesmo se o schema não existisse, fazendo:

Connection conexao = DriverManager.getConnection(url2 + "user=" + usuario + "&" + "password=" + senha);`
        Statement stmt = conexao.createStatement();
        stmt.executeUpdate("CREATE DATABASE IF NOT EXISTS meuBD");

com url2 sendo "jdbc:mysql://localhost:3306?";

A dúvida é: Dá pra fazer isso com h2 da mesma forma que faço com MySQL, apenas adicionando uma interrogação ao final da url, para conseguir uma conexão e depois criar meuBD? Ou tenho que distribuir meuBD, mesmo que vazio, junto com o meu JAR?

Mais uma vez, obrigado pela disposição em ajudar. :+1:

D

para cria-las dinamicamente uso o código (exemplo):

String sql = " DROP TABLE IF EXISTS usuarios;"

  • " CREATE TABLE usuarios ("
  • " idUsuario INTEGER unsigned NOT NULL AUTO_INCREMENT,"
  • " email text,"
  • " senha text,"
  • " PRIMARY KEY (idUsuario)"
  • " );";
PreparedStatement stmt = conexao.prepareStatement(sql);

stmt.execute();

stmt.close();

JOptionPane.showMessageDialog(null, Parabéns por adquirir este Software!!!);

Esta parte eu já tenho feito, na opção com MySQL.

Empaquei na criação do schema com h2. Conseguindo, creio que os comandos de criação de tabelas sejam os mesmos.

A propósito, antes de implementar essa ideia, a vi em uma postagem sua auxiliando outra pessoa, tempos atrás. :slightly_smiling:

SandroSoftwares

Oi amigo!
meu jar. vai sem o banco.
No momento em que o cara roda o aplicativo pela primeira vez eu crio o banco:

static String URL_H2 = "jdbc:h2:tcp://localhost/db/MEUBANCO";

Quando eu chamar essa url ele ja cria essa pasta DB e o banco dentro dela.

Conectado ao banco agora crio a estrutura das tabelas com os comandos create e etc…

Quando ele precisar inserir algo já estará pronto, será só fazer os inserts.

Os arquivos que serão distribuídos estarão dentro da pasta dist (lib (a biblioteca tem que conter o jar do h2) + jar (do aplicativo criado)) e arquivos externos como relatórios.

O processo feito aqui é muito simples…

D

Tentei desta forma, readequei minha classe de conexão, mas não obtive sucesso.

Você poderia dar uma olhadinha nela?

`import java.sql.*;

import java.util.logging.Level;

import java.util.logging.Logger;

import javax.swing.JOptionPane;

public class ConexaoBD1 {

private Connection conexao = null;
private String url = null;
private String driver = null;
private String usuario = null;
private String senha = null;
private boolean status = false;
            
public ConexaoBD1() {
    driver = "org.h2.Driver";
    url = "jdbc:h2:tcp://localhost/db/meuBD";

}

public boolean statusConnection(){
    return status;
}

public Connection getConnection(String user, String pswd) {
    usuario = user;
    senha = pswd;

    try {
        Class.forName(driver);
    } catch (ClassNotFoundException ex) {
        System.out.println("ClassNotFoundException!");
        Logger.getLogger(ConexaoBD1.class.getName()).log(Level.SEVERE, null, ex);
        return null;
    }

    try {
        System.out.println(url);
        conexao = DriverManager.getConnection(url, usuario, senha);
        status = true;
    } catch (SQLException e) {
        
        if (e.getErrorCode() == 28000) { //Caso usuário ou senha estejam inválidos
            JOptionPane.showMessageDialog(null, "Insira um nome de usuário e senha válidos!", null, JOptionPane.ERROR_MESSAGE);
            
        } 

    }
    
    System.out.println("Status da conxão: " + status);
    return conexao;
}

public void closeConnection() {
    if (conexao != null) {
        try {
            conexao.close();
            status = false;
        } catch (SQLException ex) {
            ex.printStackTrace();
            JOptionPane.showConfirmDialog(null, "Não foi possível fechar a conexão!", null, JOptionPane.ERROR_MESSAGE);
        }
    }
}

}`

SandroSoftwares

qual o erro que apresentou?
tentou ja deixar na aplicação registrado o usuário e a senha diretamente ao conectar???
sem precisar solicitar? faz isso ai só pra teste!

D

Dava o erro 90011 referente ao diretório usado.

Alterei a url para a seguinte:

url = “jdbc:h2:./db/meuBD”;

Funcionou legal! :smiley:

Agora está apresentando o erro 90130 dizendo que não é permitido utilizar PreparedStatement ao fazer consultas e atualizações. Parece que terei que utilizar a classe Statement. Como você consegue utilizar o PreparedStatement sem dar erro?

SandroSoftwares

pelo visto a instrução sql deve estar fora dos parenteses… armazenada numa string por exemplo…

O erro com o código 90130 é acionado quando um método de execução de PreparedStatement foi chamado com uma instrução SQL.

http://codenav.org/code.html?project=/com/h2database/h2/1.2.124&path=/Source%20Packages/org.h2.constant/ErrorCode.java

D

Perfeito!

O problema é que eu estava usando o PreparedStatement desta forma:

PreparedStatement st = conexao.prepareStatement(sql);
st.executeUpdate(sql); //sql sendo uma instrução de criação de tabela

Após seu comentário modifiquei o st.executeUpdate(sql) por st.execute() e funcionou tranquilo! :smiley:

Obrigado de novo, SandroSoftwares!

Criado 9 de janeiro de 2016
Ultima resposta 12 de jan. de 2016
Respostas 11
Participantes 2