Duvidas Hibernate

Caros,

duas perguntinhas de um iniciante em Hibernate:

  1. Onde coloco meus arquivos *.hbm.xml?

2)Estou testando no Acess…no arquivo hobernate.cfg.xml,qual o valor da tag?

abraços

Qualquer lugar desde que esteja dentro da sua hieráquia de pacotes do projeto, mas o legal mesmo é colocar junto com suas classes ao qual o *.hbm.xml está mapeando.

Hibernate só da suporte para Sistemas Gerenciadores de Banco de Dados. :mrgreen:

hihi, brincadeira… mas o que eu falei em cima é sério. Não sei se hibernate suporta access. Mas eu acho que não deveria suportar mesmo!

Abraços!
Thiago

Não, o Hibernate não suporta Access.

Suporta quais entao?

Esses: SQL Dialects

Opa! Opa! :smiley:

Hibernate suporta MS Access ( Microsoft Acess ) sim. Eu estou usando em uma migração de projeto da minha empresa.

Para que de o suporte primeiro você tem que escrever uma classe de dialect:

package br.com.centauro.dao;

import java.sql.Types;

import org.hibernate.cfg.Environment;
import org.hibernate.dialect.Dialect;

public class MSAccessDialect extends Dialect {
	public MSAccessDialect() {
		super();
		registerColumnType(Types.BIT, "BIT");
		registerColumnType(Types.BIGINT, "INTEGER");
		registerColumnType(Types.SMALLINT, "SMALLINT");
		registerColumnType(Types.TINYINT, "BYTE");
		registerColumnType(Types.INTEGER, "INTEGER");
		registerColumnType(Types.CHAR, "VARCHAR(1)");
		registerColumnType(Types.VARCHAR, "VARCHAR($l)");
		registerColumnType(Types.FLOAT, "DOUBLE");
		registerColumnType(Types.DOUBLE, "DOUBLE");
		registerColumnType(Types.DATE, "DATETIME");
		registerColumnType(Types.TIME, "DATETIME");
		registerColumnType(Types.TIMESTAMP, "DATETIME");
		registerColumnType(Types.VARBINARY, "VARBINARY($l)");
		registerColumnType(Types.NUMERIC, "NUMERIC");

		getDefaultProperties().setProperty(Environment.STATEMENT_BATCH_SIZE,
				"0");
	}

	public String getIdentityColumnString() {
		return "AutoNumber NOT NULL";
	}

	public String getIdentitySelectString() {
		return "select @@IDENTITY";
	}

}

Depois você tem que colocar ela no hibernate.properties

## Access
hibernate.dialect br.com.centauro.dao.MSAccessDialect
hibernate.connection.driver_class sun.jdbc.odbc.JdbcOdbcDriver
hibernate.connection.url jdbc:odbc:empresario
hibernate.connection.username centauro
hibernate.connection.password centauro

O restante é coisa do Hibernate. Para deixar este post mais completo :smiley: Quando eu comecei a mexer notei que o Access pode setar um atributo de como Permitir Comprimento Zero = Não.

Quando você tenta gravar uma String com tamanho zero dá uma exception. Para resolver este problema meu camarada Thadeu escreveu uma classe que seta todos os campos String de uma classe que tiver .length()=0 para null.

package br.com.centauro.utilitario;

import java.lang.reflect.Method;

/**
 * SetNull.java 13/07/2005
 * 
 * @author Thadeu de Russo e Carmo
 * @author Wanderley Guimarães
 * 
 * (2005) Centauro Portões
 */

public class SetNull {
	public static void setAll(Object obj) {
		try {
			Class clazz = obj.getClass();
			Method[] methods = clazz.getMethods();

			for (int i = 0; i < methods.length; i++) {
				if (methods[i].getReturnType().isAssignableFrom(String.class)) {
					String val = (String) methods[i].invoke(obj,
							(Object[]) null);

					if (val != null && val.length() == 0) {
						String nomeSetMetodo = methods[i].getName()
								.replaceFirst("get", "set");
						Method setMethod = clazz.getMethod(nomeSetMetodo,
								new Class[] { String.class });
						setMethod.invoke(obj, new Object[] { null });
					}
				}
			}
		} catch (Exception e) {
			// TODO colocar isso no log4j
		}
	}
}

Assim você precisa adicionar uma anotação na classe para que seja ignorado os campos null.

@Entity
@org.hibernate.annotations.Entity(dynamicInsert = true, dynamicUpdate = true)
public class Bfj implements Serializable {

Para saber o que são estas anotações:
http://www.hibernate.org/hib_docs/annotations/reference/en/html/entity.html#entity-hibspec-entity
http://www.hibernate.org/hib_docs/v3/reference/en/html/mapping.html#mapping-declaration-class

Acho que é isto. Se eu estiver fazendo algo errado ou que podia ser melhora espero a colaboração da galera.

Até mais,

Cara, é vivendo e aprendendo :mrgreen:

Nunca pensei que alguém ia escrever um Dialect pra access. Os relacionamentos funcionam normalmente?

Funciona normal. Acontece algumas exception do monitoramento que o hibernate faz no banco de dados. Mas nada que influencie a aplicação.

Pergunta: Ja tentou enviar este dialect como patch pro time do Hibernate? :wink:

Na verdade este é baseado no GenericDialect, ele alterar pouca coisa. Acontece que para o meu uso atual não deu nenhum pau. Mas acho que deve precisar de mais coisas para virar um Dialect distribuivel, por enquanto tá como quebra galho. :slight_smile:

Quanto tiver mais tempo vou debulhar alguns Dialect e tentar melhorar ele.

Muito maneiro. Manda pra la!!! :mrgreen:

O legal eh q vc pode fazer um dialeto para qualquer banco de dados (os caras mandaram muito bem na estrutura do projeto).

No fórum do hibernate tem umas coisas legais sobre este assunto e no projeto do wanderley2k tem umas coisas mais “escabrosas” como por exemplo usar do auto-incremento do access.

Mas que se diga de passagem da para fazer “miséria” com o hibernate :slight_smile:

Tirando que estou tendo que trabalhar com dois banco de dados diferentes. :smiley: Melhor dois arquivos de dados Access. :slight_smile:

segundo a página do hibernate “Community Supported Databases”
http://www.hibernate.org/80.html

o access é suportado sim, através do “HXTT Hibernate Support Package”
http://www.hxtt.com/hibernate.html

ainda não testei, então num sei o qto funciona… mas se tratando de access tá bom demais, hein??

Olá!

Eu estou precisando usar o hibernate com access, encontrei esse topico e tentei implementar.
O hibernate ta reconhecendo o banco, mapeando as tabelas, mas na hora do insert dá erro.
Antes do insert o hibernate da uma select max na tabela, funciona de boa, traz o valor do proximo id, mas não consegue inserir.
eu estou utilizando o save.

sessao.save(usuarioVO);

e dá o seguinte erro:?

Hibernate: select max(codUsuario) from usuario
Código retornado pelo select max: 7
Hibernate: /* insert negocio.usuario.UsuarioVO */ insert into usuario (email, senha, codUsuario) values (?, ?, ?)
2008-05-09 09:49:27,187 - 11609 WARN org.hibernate.util.JDBCExceptionReporter - SQL Error: -3500, SQLState: 37000
2008-05-09 09:49:27,187 - 11609 ERROR org.hibernate.util.JDBCExceptionReporter - [Microsoft][Driver ODBC para Microsoft Access] Instrução SQL inválida. ‘DELETE’, ‘INSERT’, ‘PROCEDURE’, ‘SELECT’ ou ‘UPDATE’ esperado.
2008-05-09 09:49:27,187 - 11609 ERROR org.hibernate.event.def.AbstractFlushingEventListener - Could not synchronize database state with session
org.hibernate.exception.SQLGrammarException: could not insert: [negocio.usuario.UsuarioVO]

Nossa muito interessante.
Eu uso aqui a seguinte URL pro Access: jdbc:odbc:Driver={Microsoft Access Driver (*.mdb)};dbq=C/banco.mdb
Já tentei por isso no properties

   hibernate.connection.url jdbc:odbc:Driver={Microsoft Access Driver (*.mdb)};dbq=C/banco.mdb

Mas tá me dando uma NullPointerException a hora que eu tento dar um session.save(obj);

Como faço quando quero acessar um .mdb específico?

ae bruna, sera que vc conseguiu inserir usando o access ? cai no mesmo problema seu … caso conseguir me posta ai …

Não sei se vai te ajudar, mas ta aí um post interessante sobre Hibernate + Access !

http://www.guj.com.br/posts/list/27514.java

e ae galera,beleza?
to precisando acessar um banco de dados access através do hibernate,
implementei o dialect que o nosso amigo aí postou,mudei o hibernate.cfg.xml,mas quando tento salvar um objeto no banco tá gerando uma exceção,parece que ele n tá achando o driver,ou tá com algum problema nessa parte,segue meu xml:

<hibernate-configuration> <session-factory> <property name="hibernate.connection.username"></property> <property name="hibernate.connection.password"></property> <property name="hibernate.connection.url">jdbc:odbc:MaoDeObra1</property> <property name="hibernate.connection.driver_class">sun.jdbc.odbc.JdbcOdbcDriver</property> <property name="hibernate.dialect">br.com.centauro.dao.MSAccessDialect</property> <property name="hibernate.hbm22ddl.auto">update</property> <property name="hibernate.show_sql">true</property> <property name="hibernate.format_sql">true</property> <mapping class="opcontroller.Beans.Funcionario" /> <!-- As classes relacionais devem ser mapeadas // Este arquivo deve estar no pacote padrão--> <mapping class="opcontroller.Beans.FilhoFuncionario" /> <mapping class="opcontroller.Beans.CursoFuncionario" /> <mapping class="opcontroller.Beans.Ocorrencia" /> </session-factory> </hibernate-configuration>

segue a exceção gerada pelo IDE:

Exception in thread "main" org.hibernate.exception.GenericJDBCException: Cannot open connection at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:140) at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:128) at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66) at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:52) at org.hibernate.jdbc.ConnectionManager.openConnection(ConnectionManager.java:449) at org.hibernate.jdbc.ConnectionManager.getConnection(ConnectionManager.java:167) at org.hibernate.jdbc.JDBCContext.connection(JDBCContext.java:160) at org.hibernate.transaction.JDBCTransaction.begin(JDBCTransaction.java:81) at org.hibernate.impl.SessionImpl.beginTransaction(SessionImpl.java:1473) at opcontroller.DAO.FuncionarioDAO.insere(FuncionarioDAO.java:27) at opcontroller.Main.main(Main.java:49) Caused by: java.sql.SQLException: [Microsoft][ODBC Driver Manager] Nome da fonte de dados n?o encontrado e nenhum driver padr?o especificado at sun.jdbc.odbc.JdbcOdbc.createSQLException(JdbcOdbc.java:6956) at sun.jdbc.odbc.JdbcOdbc.standardError(JdbcOdbc.java:7113) at sun.jdbc.odbc.JdbcOdbc.SQLDriverConnect(JdbcOdbc.java:3072) at sun.jdbc.odbc.JdbcOdbcConnection.initialize(JdbcOdbcConnection.java:323) at sun.jdbc.odbc.JdbcOdbcDriver.connect(JdbcOdbcDriver.java:174) at java.sql.DriverManager.getConnection(DriverManager.java:579) at java.sql.DriverManager.getConnection(DriverManager.java:190) at org.hibernate.connection.DriverManagerConnectionProvider.getConnection(DriverManagerConnectionProvider.java:133) at org.hibernate.jdbc.ConnectionManager.openConnection(ConnectionManager.java:446) ... 6 more Java Result: 1

alguém pode dar uma olhada no meu xml?não sei como posso arrumar isso…

@brunalaraujo
Voce disse q o hibernate tá encontrado o banco e reconhecendo as tabelas,será q vc pode postar aqui o seu xml de configuração pra eu dar uma olhada?vlw!

vlw pela atenção,galera!abraço!

Galera,

Sei que esse tópico é antigo mas eu consegui fazer funcionar e acho que vai acrescentar conhecimento caso alguem um dia precise disso.

Segue o xml de cfg do hibernate que eu usei para acessar um banco de MS Access:

<hibernate-configuration> <session-factory> <property name="hibernate.connection.username"></property> <property name="hibernate.connection.password"></property> <property name="hibernate.connection.url">jdbc:access:///D:\users\fa039420\Documents\NetBeansProjects\OpController\src\MaoDeObra1.accdb</property> <property name="hibernate.connection.driver_class">com.hxtt.sql.access.AccessDriver</property> <property name="hibernate.dialect">br.com.centauro.dao.MSAccessDialect</property> <property name="hibernate.hbm22ddl.auto">update</property> <property name="hibernate.show_sql">true</property> <property name="hibernate.format_sql">true</property> <mapping class="opcontroller.Beans.Funcionario" /> <!-- As classes relacionais devem ser mapeadas // Este arquivo deve estar no pacote padrão--> <mapping class="opcontroller.Beans.FilhoFuncionario" /> <mapping class="opcontroller.Beans.CursoFuncionario" /> <mapping class="opcontroller.Beans.Ocorrencia" /> </session-factory> </hibernate-configuration>

Utilizei o Dialect implementado por um amigo aqui do fórum,o código dele tá nesse tópico mesmo.O driver que eu usei foi o com.hxtt.sql.access.AccessDriver,precisei baixar e colocar no classpath: o “Access_Core_JDBC41.jar” e o “Access_JDBC41.jar” que eu consegui no www.hxtt.com
só isso :smiley: vlw galera!