One-to-One com Hibernate

Olá, galera.
Estou começando com Hibernate e uma dúvida insiste em me atormentar.
Dei uma boa olhada nos tópicos relacionados a esse assunto, mas ainda assim não consegui resolver.

Tenho uma entidade chamada Cte, e nela eu tenho um one-to-one com CteTomador.
Até aí tranquilo, esse relacionamento é obrigatório.
Porém existe alguns outros como Destinatário, Remetente, etc. que não são obrigatórios.

No momento de gravar meu Cte ele salvar tudo certinho, mas na hora de atualizar… hm, aí o bicho pega.

Já não sei mais o que pode estar ocorrendo. :cry:

Segue alguns códigos:

Classe Cte

@Entity
@NamedQueries({
    @NamedQuery(name = "Cte.findAll", query = "SELECT c FROM Cte c "
    + "LEFT OUTER JOIN FETCH c.cteTomador "
    + "LEFT OUTER JOIN FETCH c.cteDestinatario "
    + "LEFT OUTER JOIN FETCH c.cteExpedidor "
    + "LEFT OUTER JOIN FETCH c.cteRecebedor ")
})
public class Cte implements Serializable {


    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "id", nullable = false)
    private Integer id;

    @PrimaryKeyJoinColumn
    @OneToOne(cascade = CascadeType.ALL, mappedBy = "cte", fetch = FetchType.EAGER)
    private CteTomador cteTomador;
    @PrimaryKeyJoinColumn
    @OneToOne(cascade = CascadeType.ALL, mappedBy = "cte", fetch = FetchType.EAGER, optional = true)
    private CteDestinatario cteDestinatario;
    @PrimaryKeyJoinColumn
    @OneToOne(cascade = CascadeType.ALL, mappedBy = "cte", fetch = FetchType.EAGER, optional = true)
    private CteRemetente cteRemetente;
    @PrimaryKeyJoinColumn
    @OneToOne(cascade = CascadeType.ALL, mappedBy = "cte", fetch = FetchType.EAGER, optional = true)
    private CteExpedidor cteExpedidor;
    @PrimaryKeyJoinColumn
    @OneToOne(cascade = CascadeType.ALL, mappedBy = "cte", fetch = FetchType.EAGER, optional = true)
    private CteRecebedor cteRecebedor;

   //getters e setters

Classe CteTomador

@Entity
@XmlRootElement
@NamedQueries({})
public class CteTomador implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @Column(name = "idcte")
    @GeneratedValue(generator = "foreign")
    @GenericGenerator(name = "foreign", strategy = "foreign",
    parameters = {
        @Parameter(name = "property", value = "cte")})
    private Integer idCte;
    @JoinColumn(name = "idcliente", referencedColumnName = "id")
    @ManyToOne(fetch = FetchType.LAZY)
    private Cliente cliente;
    @JoinColumn(name = "idfornecedor", referencedColumnName = "id")
    @ManyToOne(fetch = FetchType.LAZY)
    private Fornecedor fornecedor;
    @Column(name = "clifor")
    private Character cliFor;
    @JoinColumn(name = "idcte", referencedColumnName = "id", nullable = true, insertable = true, updatable = true)
    @OneToOne(optional = true, fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    private Cte cte;
   
   //getters e setters

Classe CteRemetent

@Entity
@XmlRootElement
@NamedQueries({})
public class CteRemetente implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @Column(name = "idcte")
    @GeneratedValue(generator = "foreign")
    @GenericGenerator(name = "foreign", strategy = "foreign",
    parameters = {
        @Parameter(name = "property", value = "cte")})
    private Integer idCte;
    @JoinColumn(name = "idcliente", referencedColumnName = "id")
    @ManyToOne(fetch = FetchType.LAZY)
    private Cliente cliente;
    @JoinColumn(name = "idfornecedor", referencedColumnName = "id")
    @ManyToOne(fetch = FetchType.LAZY)
    private Fornecedor fornecedor;
    @Column(name = "clifor")
    private Character cliFor;
    @JoinColumn(name = "idcte", referencedColumnName = "id", nullable = true, insertable = true, updatable = true)
    @OneToOne(optional = true, fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    private Cte cte;

   //getters e setters

Exceção (meu karma)

javax.persistence.PersistenceException: org.hibernate.id.IdentifierGenerationException: attempted to assign id from null one-to-one property: cte at org.hibernate.ejb.AbstractEntityManagerImpl.throwPersistenceException(AbstractEntityManagerImpl.java:637) at org.hibernate.ejb.AbstractEntityManagerImpl.merge(AbstractEntityManagerImpl.java:244) at model.persistence.GenericDao.mergePojo(GenericDao.java:64) at model.persistence.dao.impl.CteDaoImpl.atualiza(CteDaoImpl.java:26) at model.persistence.service.impl.CteServiceImpl.atualiza(CteServiceImpl.java:37) at gui.gestaovendas.controller.CteController.atualiza(CteController.java:36) at gui.gestaovendas.handler.CadCteHandler.populaObjeto(CadCteHandler.java:2048) at gui.gestaovendas.handler.CadCteHandler.salvar(CadCteHandler.java:2081) at gui.gestaovendas.handler.CadCteHandler.access$400(CadCteHandler.java:92) at gui.gestaovendas.handler.CadCteHandler$5.actionPerformed(CadCteHandler.java:295) at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2018) at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2341) at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402) at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259) at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252) at java.awt.Component.processMouseEvent(Component.java:6505) at javax.swing.JComponent.processMouseEvent(JComponent.java:3321) at java.awt.Component.processEvent(Component.java:6270) at java.awt.Container.processEvent(Container.java:2229) at java.awt.Component.dispatchEventImpl(Component.java:4861) at java.awt.Container.dispatchEventImpl(Container.java:2287) at java.awt.Component.dispatchEvent(Component.java:4687) at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4832) at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4492) at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4422) at java.awt.Container.dispatchEventImpl(Container.java:2273) at java.awt.Window.dispatchEventImpl(Window.java:2713) at java.awt.Component.dispatchEvent(Component.java:4687) at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:707) at java.awt.EventQueue.access$000(EventQueue.java:101) at java.awt.EventQueue$3.run(EventQueue.java:666) at java.awt.EventQueue$3.run(EventQueue.java:664) at java.security.AccessController.doPrivileged(Native Method) at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76) at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87) at java.awt.EventQueue$4.run(EventQueue.java:680) at java.awt.EventQueue$4.run(EventQueue.java:678) at java.security.AccessController.doPrivileged(Native Method) at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76) at java.awt.EventQueue.dispatchEvent(EventQueue.java:677) at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:211) at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:128) at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:121) at java.awt.WaitDispatchSupport$2.run(WaitDispatchSupport.java:182) at java.awt.WaitDispatchSupport$4.run(WaitDispatchSupport.java:221) at java.security.AccessController.doPrivileged(Native Method) at java.awt.WaitDispatchSupport.enter(WaitDispatchSupport.java:219) at java.awt.Dialog.show(Dialog.java:1072) at java.awt.Component.show(Component.java:1651) at java.awt.Component.setVisible(Component.java:1603) at java.awt.Window.setVisible(Window.java:1013) at java.awt.Dialog.setVisible(Dialog.java:1003) at gui.gestaovendas.handler.CadCteHandler.<init>(CadCteHandler.java:187) at gui.gestaovendas.handler.ConCteHandler.editar(ConCteHandler.java:233) at gui.gestaovendas.handler.ConCteHandler.access$000(ConCteHandler.java:32) at gui.gestaovendas.handler.ConCteHandler$1.mouseClicked(ConCteHandler.java:65) at java.awt.AWTEventMulticaster.mouseClicked(AWTEventMulticaster.java:270) at java.awt.Component.processMouseEvent(Component.java:6508) at javax.swing.JComponent.processMouseEvent(JComponent.java:3321) at java.awt.Component.processEvent(Component.java:6270) at java.awt.Container.processEvent(Container.java:2229) at java.awt.Component.dispatchEventImpl(Component.java:4861) at java.awt.Container.dispatchEventImpl(Container.java:2287) at java.awt.Component.dispatchEvent(Component.java:4687) at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4832) at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4501) at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4422) at java.awt.Container.dispatchEventImpl(Container.java:2273) at java.awt.Window.dispatchEventImpl(Window.java:2713) at java.awt.Component.dispatchEvent(Component.java:4687) at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:707) at java.awt.EventQueue.access$000(EventQueue.java:101) at java.awt.EventQueue$3.run(EventQueue.java:666) at java.awt.EventQueue$3.run(EventQueue.java:664) at java.security.AccessController.doPrivileged(Native Method) at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76) at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87) at java.awt.EventQueue$4.run(EventQueue.java:680) at java.awt.EventQueue$4.run(EventQueue.java:678) at java.security.AccessController.doPrivileged(Native Method) at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76) at java.awt.EventQueue.dispatchEvent(EventQueue.java:677) at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:211) at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:128) at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:121) at java.awt.WaitDispatchSupport$2.run(WaitDispatchSupport.java:182) at java.awt.WaitDispatchSupport$4.run(WaitDispatchSupport.java:221) at java.security.AccessController.doPrivileged(Native Method) at java.awt.WaitDispatchSupport.enter(WaitDispatchSupport.java:219) at java.awt.Dialog.show(Dialog.java:1072) at java.awt.Component.show(Component.java:1651) at java.awt.Component.setVisible(Component.java:1603) at java.awt.Window.setVisible(Window.java:1013) at java.awt.Dialog.setVisible(Dialog.java:1003) at gui.gestaovendas.handler.ConCteHandler.<init>(ConCteHandler.java:54) at gui.principal.handler.menu.action.ConCteAction.actionPerformed(ConCteAction.java:37) at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2018) at org.jdesktop.swingx.JXHyperlink.fireActionPerformed(JXHyperlink.java:266) at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2341) at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402) at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259) at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252) at java.awt.AWTEventMulticaster.mouseReleased(AWTEventMulticaster.java:289) at java.awt.Component.processMouseEvent(Component.java:6505) at javax.swing.JComponent.processMouseEvent(JComponent.java:3321) at java.awt.Component.processEvent(Component.java:6270) at java.awt.Container.processEvent(Container.java:2229) at java.awt.Component.dispatchEventImpl(Component.java:4861) at java.awt.Container.dispatchEventImpl(Container.java:2287) at java.awt.Component.dispatchEvent(Component.java:4687) at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4832) at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4492) at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4422) at java.awt.Container.dispatchEventImpl(Container.java:2273) at java.awt.Window.dispatchEventImpl(Window.java:2713) at java.awt.Component.dispatchEvent(Component.java:4687) at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:707) at java.awt.EventQueue.access$000(EventQueue.java:101) at java.awt.EventQueue$3.run(EventQueue.java:666) at java.awt.EventQueue$3.run(EventQueue.java:664) at java.security.AccessController.doPrivileged(Native Method) at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76) at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87) at java.awt.EventQueue$4.run(EventQueue.java:680) at java.awt.EventQueue$4.run(EventQueue.java:678) at java.security.AccessController.doPrivileged(Native Method) at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76) at java.awt.EventQueue.dispatchEvent(EventQueue.java:677) at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:211) at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:128) at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:117) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:113) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:105) at java.awt.EventDispatchThread.run(EventDispatchThread.java:90) Caused by: org.hibernate.id.IdentifierGenerationException: attempted to assign id from null one-to-one property: cte at org.hibernate.id.ForeignGenerator.generate(ForeignGenerator.java:44) at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:99) at org.hibernate.ejb.event.EJB3MergeEventListener.saveWithGeneratedId(EJB3MergeEventListener.java:43) at org.hibernate.event.def.DefaultMergeEventListener.entityIsTransient(DefaultMergeEventListener.java:186) at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:123) at org.hibernate.impl.SessionImpl.fireMerge(SessionImpl.java:687) at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:669) at org.hibernate.engine.CascadingAction$6.cascade(CascadingAction.java:245) at org.hibernate.engine.Cascade.cascadeToOne(Cascade.java:268) at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:216) at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:169) at org.hibernate.engine.Cascade.cascade(Cascade.java:130) at org.hibernate.event.def.DefaultMergeEventListener.cascadeOnMerge(DefaultMergeEventListener.java:407) at org.hibernate.event.def.DefaultMergeEventListener.entityIsDetached(DefaultMergeEventListener.java:266) at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:120) at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:53) at org.hibernate.impl.SessionImpl.fireMerge(SessionImpl.java:677) at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:661) at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:665) at org.hibernate.ejb.AbstractEntityManagerImpl.merge(AbstractEntityManagerImpl.java:235) ... 132 more

Lembrando, uso o PostgreSQL como banco.
Se precisarem de mais códigos (handler e talz), eu posto, ou se não ficou bem explicado eu respondo tranquilo.
Galera, desde já agradeço.
[]s

Cara,

no seu banco seu relacionamento 1 - 1 pode receber null?

t+

Sim, no banco minha entidade Cte pode receber null nos relacionamentos que não sejam o do Tomador.

vc tem colocar a propriedade cascade, para que qdo vc fizer alguma insercao, alteracao ou exlcusao seja refletida nas entidade que ela faz relacionamento

t+

Então, como dá pra ver alí na classe, ele já tem o CascadeType.ALL.
Assim qualquer coisa que eu faça (merge, persiste, remove) ele atribu a mesma ação ao objeto fraco.

verifica se vc não ta mapeando tomator ou remetent ANTES de cte. tive o mesmo problema por estar mapeando a entidade dependente antes da principal.

De entidade dependente, apenas o Tomador, que entra na regra de negócio de não poder ir vazio, então não tem problema.
Selecionado o Tomador, eu salvo meu principal, seto os outros obejtos caso eles tenham sido selecionados, depois atualizo o meu principal de novo.
Não consegui descobrir o motivo, mas isso só acontece quando eu tento atualizar.
Alguma ideia?

Aê, pessoal… resolvido.
Vi num dos tópicos aqui mesmo sobre mapeamento de entidade fraca, alguma coisa assim, o seguinte link:
http://www.java2s.com/Tutorial/Java/0355__JPA/0180__One-To-One-Mapping.htm
Pensei alguns minutos, verifiquei meu código e cheguei a conclusão de que a tag optional na minha entidade fraca não poderia ser true.

Uma alteração sutil na tag optional dentro da anotação @OneToOne().
Nas minhas entidades opcionais passou de:

[code] @Entity
@XmlRootElement
@NamedQueries({})
public class CteTomador implements Serializable {

    private static final long serialVersionUID = 1L;  
    @Id  
    @Column(name = "idcte")  
    @GeneratedValue(generator = "foreign")  
    @GenericGenerator(name = "foreign", strategy = "foreign",  
    parameters = {  
        @Parameter(name = "property", value = "cte")})  
    private Integer idCte;  
    @JoinColumn(name = "idcliente", referencedColumnName = "id")  
    @ManyToOne(fetch = FetchType.LAZY)  
    private Cliente cliente;  
    @JoinColumn(name = "idfornecedor", referencedColumnName = "id")  
    @ManyToOne(fetch = FetchType.LAZY)  
    private Fornecedor fornecedor;  
    @Column(name = "clifor")  
    private Character cliFor;  
    @JoinColumn(name = "idcte", referencedColumnName = "id", nullable = true, insertable = true, updatable = true)  
    @OneToOne(optional = true, fetch = FetchType.LAZY, cascade = CascadeType.ALL)  
    private Cte cte;  
     
   //getters e setters  [/code]

Para:

[code] @Entity
@XmlRootElement
@NamedQueries({})
public class CteTomador implements Serializable {

    private static final long serialVersionUID = 1L;  
    @Id  
    @Column(name = "idcte")  
    @GeneratedValue(generator = "foreign")  
    @GenericGenerator(name = "foreign", strategy = "foreign",  
    parameters = {  
        @Parameter(name = "property", value = "cte")})  
    private Integer idCte;  
    @JoinColumn(name = "idcliente", referencedColumnName = "id")  
    @ManyToOne(fetch = FetchType.LAZY)  
    private Cliente cliente;  
    @JoinColumn(name = "idfornecedor", referencedColumnName = "id")  
    @ManyToOne(fetch = FetchType.LAZY)  
    private Fornecedor fornecedor;  
    @Column(name = "clifor")  
    private Character cliFor;  
    @JoinColumn(name = "idcte", referencedColumnName = "id", nullable = true, insertable = true, updatable = true)  
    @OneToOne(optional = false, fetch = FetchType.LAZY, cascade = CascadeType.ALL)  
    private Cte cte;  
     
   //getters e setters  [/code]

Agradeço a ajuda.
[]s