Org.hibernate.NonUniqueObjectException

Bom dia,

Sinceramente eu li muita coisa a respeito, mas não entendi. Tenho a seguinte Classe:

@Entity
@Table(schema="public", name="pessoa")
@SequenceGenerator(name="id_creator", sequenceName="pessoa_id")
public class Pessoa implements java.io.Serializable {

	private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO, generator="id_creator")
    @Column(name="id_pessoa")
    private Long id;

	@OneToOne
    @JoinColumn(name="id_escola")
    private Escola escola = new Escola();

    @OneToOne(cascade={CascadeType.ALL})
    @JoinColumn(name="id_endereco")
    private Endereco endereco = new Endereco();

    @OneToOne(cascade={CascadeType.ALL})
    @JoinColumn(name="id_contato")
    private Contato contato = new Contato();

    @OneToOne(cascade={CascadeType.ALL})
    @JoinColumn(name="id_pessoa_responsavel")
    private Pessoa responsavel = null;

    @Column(name="nome", nullable=false, length=50)
    private String nome;

    @Column(name="cpf", unique=true, nullable=false, length=14)
    private String cpf;

    @Column(name="rg", nullable=false, length=12)
    private String rg;

    @Column(name="comentario", length=255)
    private String comentario;

    @Column(name="tp_pessoa", nullable=false, length=1)
    private Character tipoPessoa;

    @Column(name="data_nascimento", nullable=false)
    @Temporal(TemporalType.DATE)
    private Date dataNascimento;

    @Column(name="data_excluido")
    @Temporal(TemporalType.DATE)
    private Date dataExcluido;

    @Column(name="excluido")
    private Short excluido;

    @OneToOne
    @JoinColumn(name="id_funcionario_exclusao")
    private Funcionario funcionarioExclusao;

   //getter and setter
}

Quando insiro um novo registro, sem o representante, insere perfeitamente. Agora se incluo, referenciando um representante, o erro é apresentado.

04/03/13 10:40 [http-bio-8080-exec-6] ERROR br.com.renaissance.controller.PessoaBean:166 - br.com.renaissance.exception.FacadeException: br.com.renaissance.exception.DAOException: org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [br.com.renaissance.entities.Pessoa#1]
04/03/13 10:40 [http-bio-8080-exec-6] ERROR br.com.renaissance.filter.ValidateSession:62 - org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [br.com.renaissance.entities.Pessoa#1]

No meu caso em questão, estou relacionando ao novo registro um representante já existente.

Meu método DAO:

	public void save(T t) throws DAOException {
		try {
			HibernateHelper.getManagedSession().save(t);
		} catch (Exception e) {
			throw new DAOException(e);
		}
	}

Desde já agradeço.

Olhe a mensagem: different object with the same identifier value was already associated with the session

Você está com uma conexão aberta e já tem um objeto com o ID passado.

Veja se na hora de salvar se sua classe já ñ tem ID e se esse ID não está sendo utilizado por outra classe.

Grande Hebert,

No momento em que vou salvar os atrubustos estão conforme abaixo:

pessoa.id = null 
pessoa.representante = pessoa.id = 1

A impressão que tenho é que ao inserir esse novo registro, parece que o hibernate está tentando inserir novamente o “representante”.

[quote=robinsonbsilva]Grande Hebert,

No momento em que vou salvar os atrubustos estão conforme abaixo:

pessoa.id = null 
pessoa.representante = pessoa.id = 1

A impressão que tenho é que ao inserir esse novo registro, parece que o hibernate está tentando inserir novamente o “representante”.
[/quote] você fez o pessoa.representante = pessoa.id = 1 na mão? Ou está automático?

eu recupero essa pessoa atraves de uma busca no BD(pois é um opcional).

depois de recuperado, atribuo o este objeto a pessoa.

[quote=robinsonbsilva]eu recupero essa pessoa atraves de uma busca no BD(pois é um opcional).

depois de recuperado, atribuo o este objeto a pessoa.[/quote]E como ele está mapeado?

@GeneratedValue?

Isso mesmo!

Você está fazendo tudo dentro da mesma transação?
open()
representante = find();
pessoa = new pessoa();
pessoa.setRepresentante(representante);
save(pessoa);
commit()
close();

Não, está assim:

//Aqui ainda estou preparando/setando os valores do objeto a ser persistido
open()
representante = find();
close(); 

//esse sequencia ocorre no momento de salvar
open()
pessoa = new pessoa();
pessoa.setRepresentante(representante);
save(pessoa);
commit()
close(); 

Seu representante está detached.

Por isso o erro.

Perfeito,

Obrigado pela ajuda.

Estou lendo: http://marcosalmeidaoliveira.blogspot.com.br/2010/12/hibernate-detached-and-merge.html

Para compreender melhor!!

*Só para conhecimento, ao invés de usar o save(), usei o merge() e salvou sem erro. MAS, quero realmente saber como salvar de forma correta.

[quote=robinsonbsilva]Perfeito,

Obrigado pela ajuda.

Estou lendo: http://marcosalmeidaoliveira.blogspot.com.br/2010/12/hibernate-detached-and-merge.html

Para compreender melhor!!

*Só para conhecimento, ao invés de usar o save(), usei o merge() e salvou sem erro. MAS, quero realmente saber como salvar de forma correta.[/quote]Aqui explica: JPA: Mini Livro - Primeiros passos e conceitos detalhados

Boa tarde Hebert,

Você poderia me dar uma dica de como resolver o seguinte problema, estou inserindo um novo registro:
BUSCA

Pessoa pessoa = pessoaDao.findByCPF(cpf);

INSERÇÃO

Contrato contrato = new Contrato(); 
contrato.setPessoa(pessoa); //nessa caso esse atributo já está persistido
contratoDao.save(contrato);

O seguinte erro é apresentado:

08/03/13 16:03 ERROR org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: br.com.renaissance.entities.Contrato
08/03/13 16:03 ERROR br.com.renaissance.exception.DAOException: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: br.com.renaissance.entities.Contrato

[quote=robinsonbsilva]Boa tarde Hebert,

Você poderia me dar uma dica de como resolver o seguinte problema, estou inserindo um novo registro:
BUSCA

Pessoa pessoa = pessoaDao.findByCPF(cpf);

INSERÇÃO

Contrato contrato = new Contrato(); 
contrato.setPessoa(pessoa);
contratoDao.save(contrato);

O seguinte erro é apresentado:

08/03/13 16:03 ERROR org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: br.com.renaissance.entities.Contrato
08/03/13 16:03 ERROR br.com.renaissance.exception.DAOException: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: br.com.renaissance.entities.Contrato

[/quote]Aqui explica: http://uaihebert.com/?p=1622

Hebert,

Não sei se pode ser a causa, mas acredito que estou tendo problemas desse tipo devido a implementação do Open Session View feita por mim.
Na teoria está tudo bem claro, mas basta rodar a aplicação que tudo vai por água abaixo!

Mais uma vez obrigado.

Grande Hebert, nada como ler a documentação, no meu caso eu não estava compreendendo o estados dos objetos, depois de entender, só chamar o método certo.

Valew.