[RESOLVIDO] Erro ao persistir com Hibernate - "object references an unsaved transient instance"

2 respostas
J

Pessoal, to com um problema no momento de persistir objetos no banco de dados.

Tenho como exemplo uma classe Produto, que pode ter várias categorias.

@Entity
public class Produto {
	@Id
	@GeneratedValue
	private Long id;
	private String nome;
	private String descricao;
	private Double preco;
	@ManyToMany
	private List<Categoria> categorias;

       //getters and setters

}

Classe de categorias:

@Entity
public class Categoria implements Serializable {
	/**
	 * 
	 */
	private static final long serialVersionUID = -4616694080322799350L;
	@Id
	@GeneratedValue
	private Long id;
	private String nmCategoria;

        //getters and setters

	/**
	 * @param nmCategoria
	 */
	public Categoria(String nmCategoria) {
		super();
		this.nmCategoria = nmCategoria;
	}
}

Ai tenho o seguinte código para adicionar produtos e suas categorias:

Produto prod = new Produto();
		
		prod.setNome("Prateleira");
		prod.setDescricao("Prateleira de livros");
		prod.setPreco(35.95);
		
		List<Categoria> categorias = new ArrayList<>();
		categorias.add(new Categoria("Teste"));
		categorias.add(new Categoria("CategoriaTeste2"));
		
		prod.setCategorias(categorias);
		
		
		
		//cria transacao de banco
		Transaction tx = session.beginTransaction();
		
		//salva o produto
		session.save(prod);
		
		//commita alterações
		tx.commit();

Pelo que entendi e vi em outros topicos, o erro ocorre porque o objeto categoria associado ao produto ainda não foi salvo no banco.
Existe uma forma de fazer com que o Hibernate faça isso "sozinho", ou seja, persistir a categoria para após relacionar ao produto.

Pergunto isso porque caso não seja possível eu teria que criar uma lista de categorias isoladamente, salvar uma a uma, pesquisar o id das mesmas e em seguida associar, certo?

Caso eu esteja errado em alguma colocação favor me corrijam.

Erro gerado:

Exception in thread "main" org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: modelo.Categoria
	at org.hibernate.engine.internal.ForeignKeys.getEntityIdentifierIfNotUnsaved(ForeignKeys.java:249)
	at org.hibernate.type.EntityType.getIdentifier(EntityType.java:510)
	at org.hibernate.type.ManyToOneType.nullSafeSet(ManyToOneType.java:165)
	at org.hibernate.persister.collection.AbstractCollectionPersister.writeElement(AbstractCollectionPersister.java:863)
	at org.hibernate.persister.collection.AbstractCollectionPersister.recreate(AbstractCollectionPersister.java:1253)
	at org.hibernate.action.internal.CollectionRecreateAction.execute(CollectionRecreateAction.java:58)
	at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:377)
	at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:369)
	at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:292)
	at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:339)
	at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:52)
	at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1234)
	at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:404)
	at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101)
	at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:175)
	at testes.AdicaoDeProduto.main(AdicaoDeProduto.java:54)

Obrigado.

2 Respostas

F

Para q o hibernate faça sozinho vc precisa usar Cascade.
Pesquise sobre Cascade.

J

fdiaz2011:
Para q o hibernate faça sozinho vc precisa usar Cascade.
Pesquise sobre Cascade.

Cara, vlw, consegui.

Utilizei o Cascade ALL e funcionou.

obrigado.

Criado 17 de junho de 2013
Ultima resposta 28 de jun. de 2013
Respostas 2
Participantes 2