[RESOLVIDO] Hibernate + Java DB embarcado: cria mas não mantém dados na base

Pessoal,

Estou desenvolvendo uma aplicação swing standalone com java web start, usando hibernate para acessar o java db embarcado nesta aplicação.
Em teste com a IDE os dados são mantidos neste banco.

Porém, ao executar fora da IDE os dados só são mantidos enquanto a aplicação está ativa. Se fechá-la e abrí-la novamente os dados já não estão mais lá.

Como proceder para que possa distribuir tal aplicação e o banco de dados ser criado na primeira execução e nos demais acessos ocorrer apenas atualizações nas tabelas deste banco, quando necessário ?

hibernante.cfg.xml:

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <property name="hibernate.connection.driver_class">org.apache.derby.jdbc.EmbeddedDriver</property> <property name="hibernate.connection.url">jdbc:derby:minhabase;create=true</property> <property name="hibernate.connection.username">usuario</property> <property name="hibernate.connection.password">senha</property> <property name="hibernate.show_sql">false</property> <property name="hibernate.format_sql">false</property> <property name="hibernate.query.factory_class">org.hibernate.hql.classic.ClassicQueryTranslatorFactory</property> <property name="hibernate.hbm2ddl.auto">create</property> <property name="hibernate.connection.pool_size">1</property> <property name="hibernate.dialect">org.hibernate.dialect.DerbyDialect</property> <property name="hibernate.default_schema">app</property> <property name="hibernate.current_session_context_class">thread</property> <mapping class="com.tfv.model.Cliente"/> <mapping class="com.tfv.model.CondicaoPagamento"/> <mapping class="com.tfv.model.Produto"/> </session-factory> </hibernate-configuration>

HibernateUtil.java:

[code]public class HibernateUtil {

private static final SessionFactory sessionFactory;

static {
    try {
        // Create the SessionFactory from standard (hibernate.cfg.xml) 
        // config file.
        sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
    } catch (Throwable ex) {
        // Log the exception. 
        System.err.println("Initial SessionFactory creation failed." + ex);
        throw new ExceptionInInitializerError(ex);
    }
}

public static SessionFactory getSessionFactory() {
    return sessionFactory;
}

}[/code]

GenericDAO.java:

[code]public class GenericDAO<T extends Serializable> {

private Session sessao;
private final Class&lt;T&gt; classePersistente;

public GenericDAO() {
    this.sessao = HibernateUtil.getSessionFactory().getCurrentSession();
    this.classePersistente = (Class&lt;T&gt;) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
}

public Session getSessao() {
    return sessao;
}

protected void salvar(T entity) {
    try {
        this.sessao.beginTransaction().begin();
        this.sessao.save(entity);
        this.sessao.beginTransaction().commit();
    } catch (Throwable t) {
        this.sessao.getTransaction().rollback();
        t.printStackTrace();
    } finally {
        fecharSessao();
    }
}

protected void alterar(T entity) {
    try {
        this.sessao.beginTransaction().begin();
        this.sessao.update(entity);
        this.sessao.beginTransaction().commit();
    } catch (Throwable t) {
        this.sessao.getTransaction().rollback();
        t.printStackTrace();
    } finally {
        fecharSessao();
    }
}

protected void deletar(T entity) {
    try {
        this.sessao.beginTransaction().begin();
        this.sessao.delete(entity);
        this.sessao.beginTransaction().commit();
    } catch (Throwable t) {
        this.sessao.getTransaction().rollback();
        t.printStackTrace();
    } finally {
        fecharSessao();
    }
}

/**
 * retorna todos os registros de determinada tabela.
 *
 * @return
 * @throws Exception
 */
public List&lt;T&gt; BuscaTodos() throws Exception {
    return this.sessao.createCriteria(classePersistente).list();
}

/**
 * método para retornar registros que possuem determinada string no campo
 * indicado no primeiro parâmetro.
 *
 * @param campo - nome do campo por onde será pesquisado.
 * @param conteudo - conteúdo a ser pesquisado no campo informado no 1º
 * parâmetro.
 * @return
 */
public List&lt;T&gt; BuscaCampoString(String campo, String conteudo) {
    this.sessao.beginTransaction().begin();
    List&lt;T&gt; aResultado = this.sessao.createCriteria(classePersistente).add(Restrictions.like(campo.toString(), "%" + conteudo + "%").ignoreCase()).list();
    this.sessao.beginTransaction().commit();
    fecharSessao();
    return aResultado;
}

/**
 * método para retornar registro que possui determinada id passada como
 * parâmetro.
 *
 * @param campo - nome do campo chave-primária
 * @param id - conteúdo a ser pesquisado no campo chave-primária
 * @return
 */
public T BuscaCampoId(String campo, String id) {
    this.sessao.beginTransaction().begin();
    T oResultado = (T) this.sessao.createCriteria(classePersistente).add(Restrictions.eq(campo.toString(), id)).uniqueResult();
    this.sessao.beginTransaction().commit();
    fecharSessao();
    return oResultado;
}

public void fecharSessao() {
    if (this.sessao != null && this.sessao.isOpen()) {
        this.sessao.getTransaction().commit();
        this.sessao.close();
    }
}

}[/code]

ClienteDAO.java:

[code]public class ClienteDAO extends GenericDAO<Cliente> {

@Override
public void salvar(Cliente cliente){
    salvar(cliente);        
}

@Override
public void alterar(Cliente cliente){
    alterar(cliente);
}

public void deletar(String id){
    Cliente c = BuscaCampoId("id", id);
    deletar(c);
}

}
[/code]

Exemplo de gravação de um cliente:

[code]…
sessao = HibernateUtil.getSessionFactory().openSession();
sessao.beginTransaction().begin();

            Cliente cliente = new Cliente();

… cliente.sets …
sessao.saveOrUpdate(cliente);
sessao.getTransaction().commit();
sessao.close();
[/code]

Se não me falha a memória, se você usa o “create=true” na string de conexão, toda vez que iniciar a aplicação ele vai recriar o banco, sendo assim, exclui os dados antigos.

Pois é. Isto resolveria eu liberando uma primeira versão com create=true e depois que todos instalassem a aplicação e executassem, liberaria nova versão sem o create=true. Mas, não tem nada melhor que isto ? Como fazer para distribuir esta aplicação java web start, ela criando no primeiro uso o banco e nos demais não criando, sem ser desta forma citada ? Suponho que deva fazer isto no HibernateUtil.java . Estou certo ?

Nos demais, apenas atualizar as tabelas quando se fizer necessário. Para isto sei que o &lt;property name="hibernate.hbm2ddl.auto"&gt; com create cria e com update atualiza as estruturas das tabelas.

No aguardo do auxílio :slight_smile:

Não sei como resolver em relação ao DerbyDB, mas você poderia utilizar o HSQLDB, dai não vai ter esse problema, porque ele não usa esse parâmetro na url.

Obrigado romarcio pela colaboração, mas pretendo usar o java db.

Alguém mais pode ajudar ?

Acho que você poderia passar sua configuração para uma configuração programática e não por xml. Dai, talvez, você consiga ao iniciar a aplicação fazer um rotina que testa se o banco já existe, se existir, você passa propriedade normal da url, sem o parâmetro “creat-true”, caso contrário, passa com o parâmetro.

romarcio,

Segui teu conselho e mudei para HSQLDB. Só estou emperrando no seguinte: ao tentar abrir a sessão ocorre o erro:

2013-05-02T12:27:38.026-0300 SEVERE could not reopen database
org.hsqldb.HsqlException: Database lock acquisition failure: lockFile: org.hsqldb.persist.LockFile@c54735ed[file =C:\Users\vicente\Documents\NetBeansProjects\TFV\banco\banco".lck, exists=false, locked=false, valid=false, ] method: openRAF reason: java.io.FileNotFoundException: C:\Users\vicente\Documents\NetBeansProjects\TFV\banco\banco".lck (A sintaxe do nome do arquivo, do nome do diretório ou do rótulo do volume está incorreta)

Este erro aconteceu após tentar abrir a sessão:

HibernateUtil não mechi. continua como informado anteriormente.

Olha meu hibernate.cfg.xml como ficou:

&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt; &lt;!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"&gt; &lt;hibernate-configuration&gt; &lt;session-factory&gt; &lt;property name="hibernate.connection.driver_class"&gt;org.hsqldb.jdbcDriver&lt;/property&gt; &lt;property name="hibernate.connection.url"&gt;jdbc:hsqldb:file:banco/banco"&lt;/property&gt; &lt;property name="hibernate.connection.username"&gt;usuario&lt;/property&gt; &lt;property name="hibernate.connection.password"&gt;senha&lt;/property&gt; &lt;property name="hibernate.show_sql"&gt;false&lt;/property&gt; &lt;property name="hibernate.format_sql"&gt;false&lt;/property&gt; &lt;property name="hibernate.query.factory_class"&gt;org.hibernate.hql.classic.ClassicQueryTranslatorFactory&lt;/property&gt; &lt;property name="hibernate.hbm2ddl.auto"&gt;update&lt;/property&gt; &lt;property name="hibernate.connection.pool_size"&gt;1&lt;/property&gt; &lt;property name="hibernate.dialect"&gt;org.hibernate.dialect.HSQLDialect&lt;/property&gt; &lt;property name="hibernate.default_schema"&gt;app&lt;/property&gt; &lt;property name="hibernate.current_session_context_class"&gt;thread&lt;/property&gt; &lt;mapping class="com.tfv.model.Cliente"/&gt; &lt;mapping class="com.tfv.model.CondicaoPagamento"/&gt; &lt;mapping class="com.tfv.model.Produto"/&gt; &lt;/session-factory&gt; &lt;/hibernate-configuration&gt;

Tenta assim:&lt;property name="hibernate.connection.url"&gt;jdbc:hsqldb:file:./banco/banco"&lt;/property&gt;

romarcio,

infelizmente continua o mesmo erro.

[quote=vicentedepaula]romarcio,

infelizmente continua o mesmo erro. [/quote]

:cry: Não sei o que pode ser.

Mas tem uma coisa estranha no erro, java.io.FileNotFoundException: C:\Users\vicente\Documents\NetBeansProjects\TFV\banco\banco".lck o HSQLDB não cria arquivo .lck, isso é coisa do Derby.

romarcio,

obrigado pela ajuda. Descobri o problema. Primeiro mudei para

Em seguida percebi que na consulta que eu estava fazendo, havia um campo que era alimentado apenas quando a aplicação java web start funcionava no modo on-line. E tal campo servia como filtro para as demais tabelas. Descoberto isto, só foi tratar a persistência deste campo na sua entidade e o problema foi solucionado.

Continuo usando o JavaDB. Com relação ao create=true usado no hibernate.connection.url, visualizei no console o seguinte:

[color=red]WARNING: Database ‘minhabase’ not created, connection made to existing database instead.[/color]

Manterei create=true até quando não houver nenhum usuário novo da aplicação.