Ajuda JBoss e Hibernate

8 respostas
tads

Olá,

Estou utilizando JBoss 3.2.3, Oracle 8.1.7, Hibernate 2.0.2.
Criei um serviço no JBoss para o hibernate onde o arquivo está igual
ao encontrado no site do Hibernate (jboss-service.xml e crio o sar):

<server>
<mbean code="net.sf.hibernate.jmx.HibernateService" name="jboss.jca:service=HibernateFactory, name=HibernateFactory">
    <depends>jboss.jca:service=RARDeployer</depends>
    <depends>jboss.jca:service=LocalTxCM,name=projds</depends>
    <attribute name="MapResources">
     //os hbm.xml aki    			
    </attribute>
    <attribute name="JndiName">java:/hibernate/HibernateFactory</attribute>
    <attribute name="Datasource">java:/projds</attribute>
    <attribute name="Dialect">net.sf.hibernate.dialect.OracleDialect</attribute>
    <attribute name="UseOuterJoin">true</attribute>
    <attribute name="ShowSql">false</attribute>
    <attribute name="UserTransactionName">UserTransaction</attribute>
    <attribute name="TransactionStrategy">net.sf.hibernate.transaction.JTATransactionFactory</attribute>
    <attribute name="TransactionManagerLookupStrategy">net.sf.hibernate.transaction.JBossTransactionManagerLookup</attribute>  
</mbean>
</server>
// Obs.: Somente o atributo dsTest de test é alterado na chamada do método updateTest(..) 

public void updateTest(Test test) 
{ 
       Session session = null; 
        Transaction tx = null; 

        try 
        { 
            session = dataSource.openSession(); 
            tx = session.beginTransaction(); 

            session.update(test, session); 

            // gets from database 
            Test aux = session.load(Test.class, test.getIdTest()); 

            // if the object from database (aux) is different than test 
            if (!test.getDsTest().equals(aux.getDsTest())) 
            { 
                 session.update(teste.getOtherObject(), session); 
            } 

            tx.commit(); 
. 
. 
. 

}

Acontece o seguinte: quando uso no JBoss, o Transaction no código acima
é o JTATransaction. Altero o dsTest e tendo buscar da base
( o objeto aux vem da base de dados, portando os dados deveriam ser os antigos, antes de executar o commit ).

O motivo pra eu pegar da base de dados e comparar com o que foi
persistido é que preciso fazer algumas verificações, como faço acima,
verificando se o atributo dsTest eu alterei ou está igual a base de dados.
Mas quando eu faço este teste no Jboss e tento buscar da base (aux)
o objeto aux é igual ao que eu alterei, ou seja, parece que ele já deu
o commit antes mesmo de eu executar o tx.commit().
Parece que ele já persistiu o objeto e já alterou na base mesmo
que não tenha dado commit.

O que pode estar acontencendo? o que posso fazer pra resolver isto?

Obrigado,

Tadeu[/code]

8 Respostas

A

O que acontece é o seguinte…
Quando o oracle faz um update na tabela, mesmo que você não tenha comitado as alterações, a sua sessão sempre vai ver os dados já modificados. Caso você execute um rollback, então os dados voltarão ao que eram.
Na hora do commit ele simplesmente torna suas alterações visíveis ao resto das sessões (e persiste, obviamente).

tads

Olá, tudo bom?

Desculpe, talvez não tenha sido fui muito claro no exemplo.
Tenho um método chamado load(…) que criei dentro de uma classe
DataSource para facilitar o desenvolvimento.
Dentro deste método eu tenho o seguinte:

public Object load(Class c, Integer generatedId) throws Exception, ObjectNotFoundException
	{
		Object o = null;
		Session session = null;
		Transaction tx = null;		
		
		try
		{
			session = factory.openSession();
			tx = session.beginTransaction();
			o = (Object) session.load(c, generatedId);
			tx.commit();
			session.flush();			
		}
		catch (Exception e)
		{
			try
			{
				tx.rollback();
			}
			catch (HibernateException e1)
			{
				throw e1;
			}

			throw e;
		}
		finally
		{
			try
			{
				session.close();
			}
			catch (HibernateException e1)
			{
				throw e1;
			}
		}		

		return o;
	}

este método cria uma nova sessão e cria uma nova transação
e persiste um determinada classe.

Este método é chamado dentro dakele outro método que passei como exemplo (escrevi método errado)…

agora o método correto:

public void updateTest(Test test) 
{ 
       Session session = null; 
        Transaction tx = null; 

        try 
        { 
            session = dataSource.openSession(); 
            tx = session.beginTransaction(); 

            session.update(test, session); 

            // gets from database --- AGORA CORRETO A CHAMADA DO
            // MÉTODO
            Test aux = dataSource.load(Test.class, test.getIdTest()); 

            // if the object from database (aux) is different than test 
            if (!test.getDsTest().equals(aux.getDsTest())) 
            { 
                 session.update(teste.getOtherObject(), session); 
            } 

            tx.commit(); 
. 
. 
. 

}

Como o método load abre uma nova sessão, então ele buscaria
da base de dados, que provavelmente é diferente dakele objeto test que
eu alterei e estou passando como parâmetro no método updateTest(…)

Mas usando o JBoss, com JTA (especificado no MBean do serviço),
Ele não carrega o objeto da base de dados no método load(…)
e sim, mesmo abrindo nova sessão no load, ele busca o objeto que
eu acabei de alterar.
Não quero busca o objeto que eu acabei de alterar e sim buscar o que
está na base. Este seria o meu problema…

Mas valew pela ajuda!!!abraço

A

Oi, tudo bem.
É o seguinte… eu entendi tua questão.

Que IDE você usa ?? Já tentou debugar e ver como está sendo instanciado esse objeto ??
Tenta comparar os objetos e vê se os dois objetos são iguais ou se são objetos diferentes com os dados iguais.

tads

Olá,

Estou usando WSAD e estou debugando no JBoss.

Olhei os ID´s do objetos instanciados e pude ver que são diferentes.

Olha lá o que acontece. Fiz dois casos, alterando a ordem
das chamadas:


Caso 1.:

  • Busco objeto da base usando o dataSource.load(…)
  • Crio a sessão e a transação
  • Faço as operações

Caso 2.:

  • Crio a sessão e a transação
  • Busco objeto da base usando o dataSource.load(…)
  • Faço as operações

Como vc pode perceber eu mudei local da chamada para buscar
o objeto da base.

Quando eu coloco ANTES de abrir a sessão e iniciar a transação (Caso 1),
O objeto é persistido de maneira que pegue o que está na base de dados,
sendo então diferente dakele que eu alterei.

Mas quando eu coloco a chamada ao load para buscar o objetos da base DEPOIS de abrir a sessão e iniciar a transação (Caso 2), os objetos têm
o mesmo valor, o que não entendo, pois como eu disse
antes, dentro do método load eu crio um outra
sessão e transação.

Se vc for ver, existe + ou - no caso 2 um encadeamento de transações.
Talver seja este o problema. Criar um sessão a transação e chamar
um método que também cria uma sessão e uma transação pode
ser que ele considere como mesma sessão, sei lá.

Mas não entendo porque só quando rodo no JBoss acontece isso.
Deve ser algo do JTA Transaction.

Mas é isso aí, estamos apanhando mas pelo menos aprendendo um pouco.

Valew pela ajuda

abraço

A

Cara,
Tb acho q é o JTA.
Bem… vou dar uma olhada aqui e se descobrir alguma coisa te aviso.

Abraços.

A

Pelo q eu estava analisando é o JTA. Na verdade, creio que é uma configuração que deve ser feita dizendo que as transações não são dependentes.

O que acontece:

Cria transação
     Update
     Cria transação
          Load
     Finaliza transação
     Update
Finaliza transação

Eu sei q dependendo da configuração a transação só será finalizada quando o último commit for feito. Creio que é isso q o JTA está fazendo.

Pode executar assim ???

Cria transação
     Update
     Load
Finaliza transação
Cria transação
     Update
Finaliza transação

Tudo tem q estar em uma só transação ???
Pq daí teremos que pesquisar as configurações do JTA e alterar a forma de iniciar e finalizar as transações.

tads

Olá asouza, tudo bom?

Eu tava procurando sobre JTA na documentação do Hibernate,
mas não achei nada que eu pudesse configurar em relação a isto.
Estou usando serviço do JBoss, onde eu configuro o JTA… Olha só
o arquivo jboss-service.xml:

<server>
<mbean code="net.sf.hibernate.jmx.HibernateService" name="jboss.jca:service=HibernateFactory, name=HibernateFactory">
    <depends>jboss.jca:service=RARDeployer</depends>
    <depends>jboss.jca:service=LocalTxCM,name=projds</depends>
    <attribute name="MapResources">
       // aki tem os hbm.xml    			
    </attribute>
    <attribute name="JndiName">java:/hibernate/HibernateFactory</attribute>
    <attribute name="Datasource">java:/projds</attribute>
    <attribute name="Dialect">net.sf.hibernate.dialect.OracleDialect</attribute>
    <attribute name="UseOuterJoin">true</attribute>
    <attribute name="ShowSql">false</attribute>
    <attribute name="UserTransactionName">UserTransaction</attribute>
    <attribute name="TransactionStrategy">net.sf.hibernate.transaction.JTATransactionFactory</attribute>
    <attribute name="TransactionManagerLookupStrategy">net.sf.hibernate.transaction.JBossTransactionManagerLookup</attribute>  
</mbean>
</server>

Creio que aki eu configuraria este tipo de coisa. Pelo menos eu acho.

Este exemplo que eu ti passei eu mudei a ordem das chamadas,
e tá beleza…mas tem outros métodos que fazem este tipo de coisa dentro de um iterate por exemplo… daí já viu, não teria como eu chamar antes de iniciar a sessão e a transação “principal”… problema!

Onde vc achou coisas sobre o JTA?

Cara, valew pela ajuda!!!

Obrigado mesmo!!

abraço

A

Eu sempre me refiro aos tutoriais da sun:
http://java.sun.com/j2ee/tutorial/1_3-fcs/doc/Transaction.html

E aos fóruns do próprio JBoss:
http://www.jboss.org/index.html?module=bb

Vou pesquisar e fazer alguns testes aqui e se descobrir mais coisas te aviso.

Abraços e estamos aqui pra isso. :smiley:

Criado 21 de junho de 2004
Ultima resposta 22 de jun. de 2004
Respostas 8
Participantes 2