Alterar mapeamento do hibernate em tempo de execução

OLá pessoal, estou envolvido em um projeto em que um dos requisitos é q a aplicação trabalhe tanto com mysql quanto com oracle, postgree e MSsqlserver, até ai beleza vamos pro hibernate, mas tive alguns problemas segue o mapeamento que estou usando :

<hibernate-mapping package="com.atual.datamodel.client.cadastros.analisecredito">
	<class name="AnaliseCredito" table="tblCADAnaliseCredito">
		<id name="codAnaliseCredito" type="integer" column="Cod_analise_credito"></id>
		<property name="creditoLimitado" column="Credito_limitado" type="string"
			 length="1" />
		<property name="prazoAtrasoMax" column="Prazo_atraso_max" type="integer" not-null="true"/>
		<property name="descricao" column="Descricao" type="string" length="50" not-null="true"/>
		<property name="limiteCredito" type="big_decimal" precision="15" scale="2">
			<column name="Limite_credito" sql-type="decimal(15,2)"></column>
		</property>
	</class>
</hibernate-mapping>

observerm a propriedade :

		<property name="limiteCredito" type="big_decimal" precision="15" scale="2">
			<column name="Limite_credito" sql-type="decimal(15,2)"></column>
		</property>

desta forma consegui comportamento aceitável no msSqlServer, no postgree e no mysql, o hibernate cria no banco um atributo com o nome Limite_credito no Mysql com o tipo decimal(15,2) no postgree e no sqlServer do tipo numeric(15,2) e tudo funciona bem ok, mas ai vamos pro oracle, e começa o problema no oracle não tenho tipo dem decimal, nem numeric, so temos number(scale,precision).

quanto retiro o trecho: <column name=“Limite_credito” sql-type=“decimal(15,2)”></column> deixo o hibernate livre pra criar no banco o tipo que ele quiser desde que tenha (scale e presion) ok mas então passo a ter o seguinte :

no oracle um atributo do tipo number(15,2) , no postgree e no sqlServer do tipo numeric(15,2) até ai beleza, mas ferra o mysql ele cria o atributo
Limite_credito com o tipo numeric(15,2) mas quando altero o hibernate.cfg.xml de create para validate–>

&lt;!-- ddl (drop and create, validate , none  , update) --&gt;
		&lt;property name="hibernate.hbm2ddl.auto"&gt;validate&lt;/property&gt;

o hibernate não consegue validar, da exceção no atributo que ele mesmo criou, ele cria o atributo mas não valida…
segue exceção:

java.lang.ExceptionInInitializerError
	at com.atual.datamodel.util.dao.HibernateGenericDao.saveOrUpdate(HibernateGenericDao.java:166)
	at com.atual.datamodel.util.dao.HibernateGenericDaoTest.testsaveOrUpdate(HibernateGenericDaoTest.java:73)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at junit.framework.TestCase.runTest(TestCase.java:168)
	at junit.framework.TestCase.runBare(TestCase.java:134)
	at junit.framework.TestResult$1.protect(TestResult.java:110)
	at junit.framework.TestResult.runProtected(TestResult.java:128)
	at junit.framework.TestResult.run(TestResult.java:113)
	at junit.framework.TestCase.run(TestCase.java:124)
	at junit.framework.TestSuite.runTest(TestSuite.java:232)
	at junit.framework.TestSuite.run(TestSuite.java:227)
	at org.junit.internal.runners.OldTestClassRunner.run(OldTestClassRunner.java:76)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:45)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
Caused by: org.hibernate.HibernateException: Wrong column type: Limite_credito, expected: numeric(15,2)
	at org.hibernate.mapping.Table.validateColumns(Table.java:261)
	at org.hibernate.cfg.Configuration.validateSchema(Configuration.java:1083)
	at org.hibernate.tool.hbm2ddl.SchemaValidator.validate(SchemaValidator.java:116)
	at org.hibernate.impl.SessionFactoryImpl.&lt;init&gt;(SessionFactoryImpl.java:317)
	at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1294)
	at com.atual.datamodel.util.HibernateUtil.&lt;clinit&gt;(HibernateUtil.java:76)
	... 21 more

há algum problema conhecido com o mysql neste tipo de dados ?

pensei que uma solução seria alterar o mapeamento em tempo de execução… tipo descobrir qual o tipo do atributo e alterar com sql-type quando for mysql e não usar sql-type para os demais bancos mas não tive sucesso, segue o código que estou tentando…


// cfg é um objeto --&gt;  public static Configuration cfg;

	if (cfg.getProperty(&quot;hibernate.dialect&quot;).equals(
				&quot;org.hibernate.dialect.MySQLInnoDBDialect&quot;)) {

			Iterator&lt;PersistentClass&gt; i = cfg.getClassMappings();
			
			System.out.println();
			System.out.println(" campos bigdecimal");
			System.out.println();

			while (i.hasNext()) {
				PersistentClass classe = (PersistentClass) i.next();
				System.out.println();
				System.out.println("classe: "
						+ classe.getMappedClass().getCanonicalName());

				Field[] campos = classe.getMappedClass().getDeclaredFields();

				for (Field field : campos) {

					if (field.getType().getName()
							.equals("java.math.BigDecimal")) {
						System.out.println(" campo: " + field.getName());

						Property prop = classe.getProperty(field.getName());

						System.out.println("propriedade obtida: "
								+ prop.getName() + " Type: "
								+ prop.getType().toString()

						);

					}

				}

			}

		}

este código executa no meu hibernateUtil…

com isso consigo descobrir todos os atributos do tipo BigDecimal, então gostaria de interferir no mapeamento através da instancia da classe PersistentClass, mas não estou conseguindo, alguém ai ja teve este problema utilizou isso?

ou tem alguma outra idéia de solução ?

desde já agradeço…

t+

Poste o erro gerado e coloque seu codigo dentro das tag ! :smiley: :smiley:

Por que você não faz algo assim:


if (banco = "Oracle") {
   cfg.setProperty("hibernate.dialect", "classe.do.dialeto.Oracle");
} else if (banco = "MySQL") {
   cfg.setProperty("hibernate.dialect", "classe.do.dialeto.MySQL");
} else if (banco = "MS SQL Server") {
   cfg.setProperty("hibernate.dialect", "classe.do.dialeto.MsSqlServer");
}

PS: Não desse jeito porco cheio de IF, mas acho que já deu pra entender a idéia…

Olá Rubem Azenha, obrigado,

mas meu problema a princípio não é setar o dialect, mas sim o tipo de dados de um determinado atributo…