Hibernate não dá erro nem grava [resolvido]

9 respostas
M

Olá pessoal,

Estou fazendo o exemplo do site: http://homepage.mac.com/edahand/projects/java/example1.html de struts com hibernate.

Por alguma razao que nao sei explicar, o hibernate nao salva e nem dá erro. Fui debugando tudo com o netbeans e ele passa por tudo bonitinho, indica sucesso, mas simplesmente nao grava no banco… não sei explicar.

Coloco abaixo algumas partes do codigo que julgo importante pra resolver o problema:

AddItemAction:

package com.edhand.example1;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

/**
 * Processes user's request to add an <code>Item</code> to the database.
 *  
 * Copyright 2003 Edward Hand
 * 
 * @author Edward Hand
 *
 */
public class AddItemAction extends Action
{

	/**
	 * execute() processes a user's request to add an <code>Item</code> to the database, 
	 * given the data in the AddItemForm.  Forwards the user back to the input page.
	 * 
	 */
	public ActionForward execute(
		ActionMapping mapping,
		ActionForm form,
		HttpServletRequest request,
		HttpServletResponse response)
	{

		/* 
		 * Cast generic form to the AddItemForm.
		 */
		AddItemForm addItemForm = (AddItemForm) form;

		/* 
		 * If the user has typed a name into the form,
		 * 
		 * Create an item with the name and description contained
		 * in the form.
		 * 
		 * Using the ItemService, add the item to the persistence
		 * layer.
		 * 
		 * Clear the form so that the two fields will be empty
		 * upon the next load.
		 */
		if (addItemForm.getName() != null)
		{
			Item item = new Item();
			item.setDescription(addItemForm.getDescription());
			item.setName(addItemForm.getName());
			item.setId(addItemForm.getId());
			ItemService.getInstance().addItem(item);
			addItemForm.clear();
		}

		/* 
		 * Always return to the "success" forward, currently
		 * configured in struts-config.xml to return the user
		 * to the AddItem.jsp.
		 */
		return mapping.findForward("success");

	}
}

ItemService:

/*
 * Created on Nov 26, 2003
 *
 * To change the template for this generated file go to
 * Window>Preferences>Java>Code Generation>Code and Comments
 */
package com.edhand.example1;

import java.util.List;

import net.sf.hibernate.HibernateException;
import net.sf.hibernate.ObjectNotFoundException;
import net.sf.hibernate.Query;
import net.sf.hibernate.Session;

/**
 * Provides an interface used to access <code>Item</code> objects from the 
 * database using Hibernate.
 * 
 * Copyright 2003 Edward Hand
 * 
 * @author Edward Hand
 *
 */
/*
 * The ItemService class uses the Singleton design pattern to provide an interface 
 * to the Struts application allowing it to work with Item objects through 
 * the persistence layer.
 * 
 * No Hibernate-related code exists above this layer.  This would allow us, in the
 * future, to switch to some other method of object persistence without making changes
 * to the Struts-related code in the application.
 *  
 */
public class ItemService
{

	private static ItemService instance = null;

	private ItemService()
	{

	}

	/**
	 * getInstance() returns the instance of the <code>ItemService</code> singleton.
	 * 
	 * @return <code>ItemService</code> singleton.
	 */
	public static synchronized ItemService getInstance()
	{
		/*
		 * Creates the Singleton instance, if needed.
		 * 
		 */
		if (instance == null)
		{
			instance = new ItemService();
		}
		return instance;
	}

	/**
	 * getItem() returns <code>Item</code> object from database with given id.  If
	 * the user is not found, will return null.
	 * 
	 * @param id The <code>Long</code> id of desired <code>Item</code> 
	 * @return <code>Item</code> with given id, if it exists.  Otherwise, returns null.
	 */
	public Item getItem(Long id)
	{

		/*
		 * Use the ConnectionFactory to retrieve an open
		 * Hibernate Session.
		 * 
		 */
		Session session = ConnectionFactory.getInstance().getSession();

		try
		{
			/*
			 * Calls the load method on the Hibernate session object
			 * to retrieve the Item with the provided id.
			 */
			return (Item) session.load(Item.class, id);
		}
		/*
		 * If the object is not found, i.e., no Item exists with the
		 * requested id, we want the method to return null rather 
		 * than throwing an Exception.
		 * 
		 */
		catch (ObjectNotFoundException onfe)
		{
			return null;
		}
		catch (HibernateException e)
		{
			/*
			 * All Hibernate Exceptions are transformed into an unchecked
			 * RuntimeException.  This will have the effect of causing the
			 * user's request to return an error.
			 * 
			 */
			System.err.println("Hibernate Exception" + e.getMessage());
			throw new RuntimeException(e);
		}
		/*
		 * Regardless of whether the above processing resulted in an Exception
		 * or proceeded normally, we want to close the Hibernate session.  When
		 * closing the session, we must allow for the possibility of a Hibernate
		 * Exception.
		 * 
		 */
		finally
		{
			if (session != null)
			{
				try
				{
					session.close();
				}
				catch (HibernateException e)
				{
					System.err.println("Hibernate Exception" + e.getMessage());
					throw new RuntimeException(e);
				}

			}
		}

	}

	/** 
	 * updateItem() updates specfied <code>Item</code> through Hibernate.
	 * 
	 * @param item An <code>Item</code> to be updated
	 */
	public void updateItem(Item item)
	{
		/*
		 * Use the ConnectionFactory to retrieve an open
		 * Hibernate Session.
		 * 
		 */
		Session session = ConnectionFactory.getInstance().getSession();

		try
		{
			/*
			 * Update the state of the item using the Hibernate session's update method.
			 * 
			 * Call the flush method to ensure that the object in saved.
			 * 
			 */
			session.update(item);
			session.flush();
		}
		catch (HibernateException e)
		{
			System.err.println("Hibernate Exception" + e.getMessage());
			throw new RuntimeException(e);
		}
      /*
       * Regardless of whether the above processing resulted in an Exception
       * or proceeded normally, we want to close the Hibernate session.  When
       * closing the session, we must allow for the possibility of a Hibernate
       * Exception.
       * 
       */
		finally
		{
			if (session != null)
			{
				try
				{
					session.close();
				}
				catch (HibernateException e)
				{
					System.err.println("Hibernate Exception" + e.getMessage());
					throw new RuntimeException(e);
				}

			}
		}

	}

	/**
	 * getItemList() returns list of all <code>Item</code> objects stored in the database. 
	 * 
	 * @return <code>List</code> of <code>Item</code> objects.
	 */
	public List getItemList()
	{
		/*
		 * Use the ConnectionFactory to retrieve an open
		 * Hibernate Session.
		 * 
		 */
		Session session = ConnectionFactory.getInstance().getSession();

		try
		{
			/*
			* Build HQL (Hibernate Query Language) query to retrieve a list
			* of all the items currently stored by Hibernate.
			 */
			Query query =
				session.createQuery(
					"select item from com.edhand.example1.Item item order by item.name");
			return query.list();

		}
		catch (HibernateException e)
		{
			System.err.println("Hibernate Exception" + e.getMessage());
			throw new RuntimeException(e);
		}
		/*
		 * Regardless of whether the above processing resulted in an Exception
		 * or proceeded normally, we want to close the Hibernate session.  When
		 * closing the session, we must allow for the possibility of a Hibernate
		 * Exception.
		 * 
		 */
		finally
		{
			if (session != null)
			{
				try
				{
					session.close();
				}
				catch (HibernateException e)
				{
					System.err.println("Hibernate Exception" + e.getMessage());
					throw new RuntimeException(e);
				}

			}
		}
	}

	/**
	 * addItem() inserts new <code>Item</code> into the database through Hibernate.
	 * 
	 * @param item A new <code>Item</code> to be added.
	 */
	public void addItem(Item item)
	{

		Session session = ConnectionFactory.getInstance().getSession();

		try
		{
			session.save(item);
			session.flush();
		}
		catch (HibernateException e)
		{
			System.err.println("Hibernate Exception" + e.getMessage());
			throw new RuntimeException(e);
		}
		/*
		 * Regardless of whether the above processing resulted in an Exception
		 * or proceeded normally, we want to close the Hibernate session.  When
		 * closing the session, we must allow for the possibility of a Hibernate
		 * Exception.
		 * 
		 */
		finally
		{
			if (session != null)
			{
				try
				{

					session.close();
				}
				catch (HibernateException e)
				{
					System.err.println("Hibernate Exception" + e.getMessage());
					throw new RuntimeException(e);
				}

			}
		}

	}

}

ConnectionFactory:

/*
 * Created on Nov 25, 2003
 *
 * To change the template for this generated file go to
 * Window>Preferences>Java>Code Generation>Code and Comments
 */
package com.edhand.example1;

import net.sf.hibernate.HibernateException;
import net.sf.hibernate.MappingException;
import net.sf.hibernate.Session;
import net.sf.hibernate.SessionFactory;
import net.sf.hibernate.cfg.Configuration;

/**
 * Singleton class that creates and returns an open Hibernate <code>Session</code> to the user.
 * 
 * Copyright 2003 Edward Hand
 * 
 * @author Edward Hand
 *
 */
/* 
 * This class was created to encapsulate the Hibernate SessionFactory and assist
 * the service layer, in this example consisting of ItemService.
 * 
 */ 
public class ConnectionFactory
{

	private static ConnectionFactory instance = null;
	private SessionFactory sessionFactory = null;

	private ConnectionFactory()
	{
		// Establish SessionFactory for Hibernate
		try
		{

			/*
			 * The Hibernate Configuration will contain all the classes to be
			 * persisted by Hibernate.  For each class persisted, Hibernate will
			 * expect to find a ClassName.hbm.xml file in the same location as the
			 * class file.  This XML file will define the mapping between the Java
			 * object and the database.
			 * 
			 * To add additional classes to the configuration, you may cascade the
			 * method calls thusly:
			 * 
			 * Configuration cfg = new Configuration().
			 *                         addClass(Foo.class).
			 *                         addClass(Bar.class);
			 * 
			 */
			Configuration cfg = new Configuration().addClass(Item.class);

			sessionFactory = cfg.buildSessionFactory();

		}
		catch (MappingException e)
		{
			/*
			 * Upon encountering a Hibernate generated Exception, we are throwing
			 * an unchecked RuntimeExcpetion that will cause the user's
			 * request to fail.
			 * 
			 */
			System.err.println("Mapping Exception" + e.getMessage());
			throw new RuntimeException(e);
		}
		catch (HibernateException e)
		{
			/*
			 * Upon encountering a Hibernate generated Exception, we are throwing
			 * an unchecked RuntimeExcpetion that will cause the user's request to fail.
			 * 
			 */
			System.err.println("Hibernate Exception" + e.getMessage());
			throw new RuntimeException(e);
		}

	}

	/** 
	 * getInstance() returns the instance of the ConnectionFactory singleton.
	 * 
	 * Example call to retrieve session:
	 * 
	 * <pre>
	 * Session session = ConnectionFactory.getInstance().getSession();
	 * </pre>
	 * 
	 * @return Instance of the <code>ConnectionFactory</code> singleton.
	 */
	public static synchronized ConnectionFactory getInstance()
	{
		/* 
		 * If the instance of the Singleton has not been created, create and
		 * return.
		 */
		if (instance == null)
		{
			instance = new ConnectionFactory();
		}
		return instance;
	}

	/**
	 * getSession() returns a Hibernate <code>Session</code>
	 * 
	 * @return <code>Session</code> retrieved from Hibernate <Code>SessionFactory</code>
	 */
	public Session getSession()
	{
		try
		{
			/*
			 * Use the Hibernate Session Factory to return an open session to the caller.
			 */
			Session s = sessionFactory.openSession();
			return s;
		}
		catch (HibernateException e)
		{
			/*
			 * Upon encountering a Hibernate generated Exception, we are throwing
			 * an unchecked RuntimeExcpetion that will cause the user's request to fail.
			 * 
			 */
			System.err.println("Hibernate Exception" + e.getMessage());
			throw new RuntimeException(e);
		}
	}

}

Item.hbm.xml:

<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE hibernate-mapping PUBLIC
   "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
   "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">

<hibernate-mapping>
   <class name="com.edhand.example1.Item" table="item" >
         <id name="id" column="id" type="java.lang.Long"> 
             <generator class="assigned"/> 
         </id> 
      <property name="name" column="name" type="java.lang.String" />
      <property name="description" column="description" type="java.lang.String" />
   </class>
</hibernate-mapping>

O que fiz de diferente do exemplo foi apenas mudar o banco pro Firebird e mudar o id pra assigned, pra jogar o valor dele também.

Alguem já passou por problema semelhante e poderia me ajudar?

9 Respostas

M

Estranho, não vi nenhuma transação sendo iniciada e terminada nesse exemplo.

Sem transações, não tem mudança no banco de dados.

M

É isso que eu chamo de pesquisa insuficiente.

Agradeço, já foi resolvido.

M

Só selects, inserts e updates não funcionam sem transação (a não ser que o seu driver esteja auto-commit, o que é terrívelmente feio).

T

noelrocha:
pergunta demente …

com mysql funciona sem abrir transação?!

pq uam vez fiz um teste com mysql e nao dei begintrasaction …

Provavelmente você criou as tabelas do MySQL usando o padrão (MyISAM), e essas tabelas não dão suporte a transações. Para usar transações teria de criar as bases como InnoDB (se não me engano).

M

Você pode usar ThreadLocal pra ter apenas uma sessão na thread e todos os DAOs acessarem ela, isso não vai acontecer.

E o problema não é que não é possível ter duas sessões, mas você não pode colocar o mesmo objeto em duas sessões diferentes.

N

pergunta demente …

com mysql funciona sem abrir transação?!

pq uam vez fiz um teste com mysql e nao dei begintrasaction …

N

entendi …

uma outra duvida sobre transações …

estou tendo problemas na hora de inserir dados aleatorios …

tenho uma tabela chamado e dentro da tabela tenho um campo empresa …

dentro do meu “for” p/ inserir chamados eu dou um load em uma empresa aleatoria e coloco dentro do meu chamado e dou um save …

p/ inserir os chamados eu tenho um daoChamado …
e p/ pegar uma Empresa aleatoria (load) eu tenho um daoEmpresa …

faço algo do tipo:

DAOChamado daoChamado = DAOFactory.getDAOChamado() ;
DAOEmpresa daoEmpresa = DAOFactory.getDAOEmpresa() ; 
for (Integer i = 0; i<100; i++){
  Chamado chamado = new Chamado() ;
  chamado.setDescricao("Teste " + i) ;
  chamado.setEmpresa(daoEmpresa.load(1))  ;
  daoChamado.save(chamado) ;

}

o codigo nao eh exatamente esse, meu dao é generico, mas funciona da mesma forma …

tirando o fato de ter q dar commit a cada save (se alguem souber uma forma de melhorar ou me dizer q não faz diferença dar commit a cada registro ou no final) …

ao dar um save(chamado) estou tento este erro:

Exception in thread "main" org.hibernate.HibernateException: illegally attempted to associate a proxy with two open Sessions
	at org.hibernate.proxy.AbstractLazyInitializer.setSession(AbstractLazyInitializer.java:68)
	at org.hibernate.engine.PersistenceContext.reassociateProxy(PersistenceContext.java:520)
	at org.hibernate.engine.PersistenceContext.reassociateIfUninitializedProxy(PersistenceContext.java:486)
	at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.reassociateIfUninitializedProxy(DefaultSaveOrUpdateEventListener.java:74)
	at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:57)
	at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:468)
	at org.hibernate.engine.Cascades$5.cascade(Cascades.java:154)
	at org.hibernate.engine.Cascades.cascadeAssociation(Cascades.java:771)
	at org.hibernate.engine.Cascades.cascade(Cascades.java:720)
	at org.hibernate.engine.Cascades.cascade(Cascades.java:847)
	at org.hibernate.event.def.AbstractSaveEventListener.cascadeBeforeSave(AbstractSaveEventListener.java:332)
	at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:214)
	at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:160)
	at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:95)
	at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:184)
	at org.hibernate.event.def.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:33)
	at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:173)
	at org.hibernate.event.def.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:27)
	at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:69)
	at org.hibernate.impl.SessionImpl.save(SessionImpl.java:481)
	at org.hibernate.impl.SessionImpl.save(SessionImpl.java:476)
	at br.com.rfc.dao.DAO.salva(DAO.java:23)
	at br.com.rfc.hibernate.InsereDadosTeste.main(InsereDadosTeste.java:162)

pelo q entendi nao posso ter duas sessões abertas …
só nao entendi o pq e como posso resolver isso …

valeu galera

N

entendi a parte de ter o mesmo objeto em sessões diferentes …

não entendi mto bem o negocio da threadlocal …

vou dar uma olhada …

mas ja sei q tem solução … hehehe

N

Cara, valeu … encontrei sobre ThreadLocal …

achei interessante e bem util quando tenho num mesmo request varios acessos ou no meu caso, no main onde gera muitos dados em entidades diferentes é bem util pois reciclo uma mesma session e não me preocupo com transaction …

porem, quando tenho apenas um requisição no banco, me pareceu melhor abrir uma sessão “exclusiva” pq assim não corro o risco de pegar uma outra thread q não eh minha …

hj, meu dao recebe a sessão q ele vai usar …
e uso uma factory q faz isso p/ mim …

vou implementar na minha factory essa segunda forma de pegar um dao de uma sessão da threadlocal …

quem quiser dar uma olhada em threadlocal:
http://www.hibernate.org/42.html

e sobre Open Session in View:
http://www.hibernate.org/43.html

Criado 20 de junho de 2005
Ultima resposta 15 de jul. de 2005
Respostas 9
Participantes 4