HIBERNATE: TransientObjectException

Tenho o seguinte erro aparecendo toda vez que tento atualizar um registro:

06:44:16,119 ERROR [stderr] (http-srvapp02.indaiatuba.sp.gov.br-172.16.1.6-8080-23) org.hibernate.TransientObjectException: object is an unsaved transient instance - save the transient instance before merging: br.gov.sp.indaiatuba.koch.model.entity.Endereco 06:44:16,120 ERROR [stderr] (http-srvapp02.indaiatuba.sp.gov.br-172.16.1.6-8080-23) at org.hibernate.event.def.DefaultMergeEventListener.getTransientCopyCache(DefaultMergeEventListener.java:142) 06:44:16,121 ERROR [stderr] (http-srvapp02.indaiatuba.sp.gov.br-172.16.1.6-8080-23) at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:90)
Ta ok, até ai eu sei que deveria salvar o endereço uma vez que ele ainda não está salvo, para poder atualizar a entidade anterior que já estava salva. Segue o trecho que verifica se salva ou não o endereço que pode ser a causa do problema hoje:

if (paciente.getPessoa().getEndereco() != null) { if ( paciente.getPessoa().getEndereco().getLogradouro().getNome() == null || paciente.getPessoa().getEndereco().getBairro().getNome() == null || paciente.getPessoa().getEndereco().getCidade().getNome() == null || paciente.getPessoa().getEndereco().getEstado().getNome() == null) { paciente.getPessoa().setEndereco(null); } } try { if (paciente.getId() == null || paciente.getId() == 0) { pacienteDAO.salvar(paciente); }else{ pacienteDAO.atualizar(paciente); } if (paciente.getPessoa().getEndereco().getLogradouro().getNome() != null) { if (!paciente.getPessoa().getEndereco().getLogradouro().getNome().equals("")) { EnderecoRN enderecoRN = new EnderecoRN(); enderecoRN.salva(paciente.getPessoa().getEndereco()); } } } catch (Exception e) { e.printStackTrace(); }
para que possam entender vou colocar a base das entidades. Para essas entidades relacionadas temos 3 principais.
Paciente:

public class Paciente implements Serializable { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "paciente_id_seq") @SequenceGenerator(name = "paciente_id_seq", sequenceName = "saude.paciente_id_seq", allocationSize = 1) private Long id; @Column(name = "cartao_sus") private String cartaoSUS; @OneToOne(cascade = CascadeType.ALL) @JoinColumn(name = "fk_pessoa") private Pessoa pessoa = new Pessoa(); // Eu omiti o resto pois não é relevante para o caso. }
Pessoa:

public class Pessoa implements Serializable { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "pessoa_id_seq") @SequenceGenerator(name = "pessoa_id_seq", sequenceName = "saude.pessoa_id_seq", allocationSize = 1) private Long id; @OneToOne(cascade = CascadeType.ALL, mappedBy = "pessoa") private CaracteristicasPessoais caracteristicasPessoais = new CaracteristicasPessoais(); @Column(name = "data_nascimento") private Date dataNascimento; @OneToOne(mappedBy = "pessoa", fetch = FetchType.LAZY) @Fetch(value = FetchMode.JOIN) private Endereco endereco = new Endereco(); private String nome; // Mais omissões!
Endereço:

public class Endereco implements Serializable { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "endereco_id_seq") @SequenceGenerator(name = "endereco_id_seq", sequenceName = "saude.endereco_id_seq", allocationSize = 1) private Long id; @OneToOne @JoinColumn(name = "fk_bairro") private Bairro bairro = new Bairro(); private String cep; @OneToOne @JoinColumn(name = "fk_cidade") private Cidade cidade = new Cidade(); @OneToOne @JoinColumn(name = "fk_estado") private Estado estado = new Estado(); @OneToOne @JoinColumn(name = "fk_logradouro") private Logradouro logradouro = new Logradouro(); private String numero; @OneToOne @JoinColumn(name = "fk_pessoa") private Pessoa pessoa; // Omissões e aqui mora o problema os antigos programadores colocaram a referencia inversa aqui o endereço é quem guarda a chave para a pessoa e não o contrário que pra mim seria o mais comum.
Tendo dito isso, vou a mais explicações: O endereço acaba não sendo salvo no banco dando o erro apontado diversas vezes, porem a estrutura que salva o endereço ela pode salva-lo ou não, com o paciente não sendo salvo como a referencia é contrária eu não posso salvar o endereço primeiro pois o erro seria pior, porem temos 3 ambientes aqui e o erro apontado só acontece em produção e começou sem nenhum aviso prévio rsrsrs

eu já estou ficando louco com esse nó aqui, nada do que faço faz esse erro parar.

Bom dia!

Não sei se vai te ajudar!

Existem três tipo estado para os objetos no hibernate que podem ser visto aqui na sesão 10.1 http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/objectstate.html.

Bom para serem persistidos os objetos tem que estar no estado Persistent, Não notei como você usa seus DAOs, com GenericDAO etc, mas enfim, em alguma lugar etá faltando um merge(), clear(), alguma coisa desse tipo.

Qualquer coisa posta ai!

Até mais…

Vc chegou a debugar para ver onde exatamente q ocorre o erro ?

Sobre esse trecho:
if (paciente.getId() == null || paciente.getId() == 0) {
pacienteDAO.salvar(paciente);

Não sei oq está por trás do eu método salvar, mas vc permite ele salvar um novo paciente com id setado pra zero ?
Dependendo do método q utiliza para persistir pode dar problema tb.

Verdade faltaram o DAO que realmente trabalha com o hibernate

salvar executa session.save(entidade);
atualizar executa session.merge(entidade);

o problema estava nos cascades estou testando uma nova mudança na entidade pessoa adicionando um cascade para o endereço e removendo a verificação se devo ou não salvar o endereço deixando isso para o hibernate, a unica coisa que mantive foi os iffs que anulam o objeto do endereço caso ele seja inválido.

Assim que concluir os testes eu mudo pra resolvido.