Hibernate - Relacionamento pai-filho 1-1

Galera,estou usando o hibernate em uma aplicação e tentando criar um relacionamento pai-filho 1-1 entre Usuaria(o pai) e RegistroGeralUsuaria(o filho);
Tenho o seguinte esquema relacional da aplicação:

Tabelas:

Usuaria
id;

RegistroGeralUsuaria
id;
numero;
OrgaoExpedidorRG_id;
Usuaria_id;

OrgaoExpedidorRG
id;

Dessa forma,criei os seguintes mapeamentos

@Embeddable
public class RegistroGeralUsuaria implements Serializable{

private Usuaria usuaria;

@Parent
public Usuaria getUsuaria(){
return this.usuaria;
}

}

public class Usuaria implements Serializable{

private RegistroGeralUsuaria registroGeralUsuaria;

@Embedded
@JoinTable(name=“RegistroGeralUsuaria”, uniqueConstraints=@UniqueConstraint(columnNames={“OrgaoExpedidorRG”, “numero”}),
joinColumns=@JoinColumn(name=“Usuaria_id”, nullable=false)
)
public RegistroGeralUsuaria getRegistroGeralUsuaria(){
return this.registroGeralUsuaria;
}

No entanto o Hibernate não reconhece que a tabela que contem os campo número e orgaoExpedidorRG é a tabela RegistroGeralUsuaria;
A SQL gerada é a seguinte:
insert into Usuaria (CPF, numero, OrgaoExpedidorRG_id, dataDeNascimento, nome) values (?, ?, ?, ?, ?);
O que,obviamente,causa um erro.

Sei que para resolver o problema é só relacionar OrgaoExpedidorRG diretamente com a Usuaria,e descolar o número e o OrgaoExpedidorRG para a tabela,no entanto,não quero fazer isso.
Será que o JPA ou o hibernate não permitam que eu faça um mapeamento pai-filho deste tipo?

Já tirei o embedded do getRegistroUsuaria() mas o resultado é o mesmo.

Agradeço desde já a ajuda.

Primeiro de tudo, comece lendo aqui: http://www.guj.com.br/posts/list/50115.java

Agora, em relação à sua dúvida, queria saber pq vc quer fazer assim.
P/ que complicar tanto?

Se “Usuaria” só tem um atributo e OrgaoExpeditorRG também só tem um atributo, pq eles não são campos de RegistroGeralUsuaria?
Sugiro que melhore seu esquema relacional e pense melhor no problema que você está querendo resolver. Normalmente a solução mais simples é a mais correta.

[]´s

Apenas tirei os campos das classes. A única classe completa é a RegistroGeralUsuaria.
Estou fazendo o mapeamento dessa forma, exatamente, porque existem outros atributos. Por uma questão de organização.

No SQL dá para ver os campos da classe.Melhor,vou postar o código completo dessas três entidades:

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package entity;


import java.io.Serializable;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.UniqueConstraint;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;


/**
 *
 * @author helder
 */
@Entity
@Table(name = "Usuaria", uniqueConstraints={@UniqueConstraint(columnNames="CPF")})
@NamedQueries(value={
    @NamedQuery(name="allUsuaria", query="from Usuaria"),
    @NamedQuery(name="loadUsuariaFromCPF", query="from Usuaria where CPF like :cpf")
})
public class Usuaria implements Serializable{

    private static final long serialVersionUID = 1L;
    private Integer id;
    private String nome;
    private String CPF;
    private RegistroGeralUsuaria RG;
    private Date dataDeNascimento;
    private Set<String> telefones = new HashSet<String>();

    public Usuaria() {
    }

    @Id
    @GeneratedValue
    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }


    @Column(nullable=false, length=60)
    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    @Column(name="CPF", nullable=false, unique=true, length=11)
    public String getCPF() {
        return CPF;
    }

    public void setCPF(String CPF) {
        this.CPF = CPF;
    }

    @Embedded
    @JoinTable(name="RegistroGeralUsuaria", uniqueConstraints=@UniqueConstraint(columnNames={"OrgaoExpedidorRG", "numero"}),
        joinColumns=@JoinColumn(name="Usuaria_id", nullable=false)
    )
    public RegistroGeralUsuaria getRG() {
        return RG;
    }

    public void setRG(RegistroGeralUsuaria RG) {
        this.RG = RG;
    }

    @Temporal(javax.persistence.TemporalType.DATE)
    @Column(nullable=false)
    public Date getDataDeNascimento() {
        return dataDeNascimento;
    }

    public void setDataDeNascimento(Date dataDeNascimento) {
        this.dataDeNascimento = dataDeNascimento;
    }

    @ElementCollection
    @CollectionTable(name="Telefone", uniqueConstraints=@UniqueConstraint(columnNames = {"numero", "Usuaria_id"}))
    @Column(name="numero", nullable=false, length=11)
    public Set<String> getTelefones() {
        return telefones;
    }

    public void setTelefones(Set<String> telefones) {
        this.telefones = telefones;
    }

    public boolean addTelefone(String numero){
        return this.telefones.add(numero);
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final Usuaria other = (Usuaria) obj;
        if ((this.CPF == null) ? (other.CPF != null) : !this.CPF.equals(other.CPF)) {
            return false;
        }
        return true;
    }

    @Override
    public int hashCode() {
        int hash = 5;
        hash = 79 * hash + (this.CPF != null ? this.CPF.hashCode() : 0);
        return hash;
    }

}

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package entity;

import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Embeddable;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import org.hibernate.annotations.Parent;

/**
 *
 * @author helder
 */
@Embeddable
public class RegistroGeralUsuaria implements Serializable{

    private static final long serialVersionUID = 1L;
    private String numero;
    private OrgaoExpedidorRG orgaoExpedidorRG;
    private Usuaria usuaria;

    public RegistroGeralUsuaria() {
    }

    @Column(nullable=false, length=14)
    public String getNumero() {
        return numero;
    }

    public void setNumero(String numero) {
        this.numero = numero;
    }

    @ManyToOne
    @JoinColumn(name="OrgaoExpedidorRG_id", nullable=false)
    public OrgaoExpedidorRG getOrgaoExpedidorRG() {
        return orgaoExpedidorRG;
    }

    public void setOrgaoExpedidorRG(OrgaoExpedidorRG orgaoExpedidorRG) {
        this.orgaoExpedidorRG = orgaoExpedidorRG;
    }

    @Parent
    public Usuaria getUsuaria() {
        return usuaria;
    }

    public void setUsuaria(Usuaria usuaria) {
        this.usuaria = usuaria;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final RegistroGeralUsuaria other = (RegistroGeralUsuaria) obj;
        if ((this.numero == null) ? (other.numero != null) : !this.numero.equals(other.numero)) {
            return false;
        }
        if (this.orgaoExpedidorRG != other.orgaoExpedidorRG && (this.orgaoExpedidorRG == null || !this.orgaoExpedidorRG.equals(other.orgaoExpedidorRG))) {
            return false;
        }
        return true;
    }

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 79 * hash + (this.numero != null ? this.numero.hashCode() : 0);
        hash = 79 * hash + (this.orgaoExpedidorRG != null ? this.orgaoExpedidorRG.hashCode() : 0);
        return hash;
    }
  
}

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package entity;

import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;

/**
 *
 * @author helder
 */
@Entity
@NamedQueries(value={
    @NamedQuery(name="allOrgaoExpedidorRGFromEstadoId", query="from OrgaoExpedidorRG where estado.id = :estadoId")
})
@Table(name="OrgaoExpedidorRG", uniqueConstraints=@UniqueConstraint(columnNames={"Estado_id", "nome"}))
public class OrgaoExpedidorRG implements Serializable{

    private static final long serialVersionUID = 1L;
    private Integer id;
    private String nome;
    private Estado estado;

    public OrgaoExpedidorRG() {
    }

    @Id
    @GeneratedValue
    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    @Column(nullable=false, length=40)
    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    @ManyToOne
    @JoinColumn(name="Estado_id", nullable=false)
    public Estado getEstado() {
        return estado;
    }

    public void setEstado(Estado estado) {
        this.estado = estado;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final OrgaoExpedidorRG other = (OrgaoExpedidorRG) obj;
        if ((this.nome == null) ? (other.nome != null) : !this.nome.equals(other.nome)) {
            return false;
        }
        if (this.estado != other.estado && (this.estado == null || !this.estado.equals(other.estado))) {
            return false;
        }
        return true;
    }

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 37 * hash + (this.nome != null ? this.nome.hashCode() : 0);
        hash = 37 * hash + (this.estado != null ? this.estado.hashCode() : 0);
        return hash;
    }

}

Eu acho que esse tipo de relacionamento é comum. Pensei que o hibernate faria isso sem necessidade de mapear RegistroGeralUsuaria como uma entidade.

Se puder ajudar,agradeço… Não encontrei nada no guia do referência do hibernate.
Estou usando o Hibernate 3.5.4

Não entendi, qual o problema de mapear a classe RegistroGeralUsuaria como uma entidade e fazer um simples @OneToOne?

e meio offtopic, sei que nao vem ao caso, mas eu estou tão curioso porque UsuariA, primeira vez que eu vejo isso, nada de papo machista nem nada do tipo, mas é q é realmente unusual…

O ciclo de vida de RegistroGeralUsuaria está diretamente associado ao ciclo de vida da Usuaria. Enfim, é uma composição.
É uma questão de organização,não deslocar os campos de RegistroGeralUsuaria para Usuaria.
Para a camada de cima da aplicação,também vai ficar mais interessante de se trabalhar.

Esperava que o Hibernate permitisse fazer uma associação dessa,mas pelo visto,do jeito que estou querendo,um relacionamento de composição 1-1, sendo o lado filho mapeado em uma tabela separada não é permitido.
Vlw pela força.

[quote=brunoskrebs]
e meio offtopic, sei que nao vem ao caso, mas eu estou tão curioso porque UsuariA, primeira vez que eu vejo isso, nada de papo machista nem nada do tipo, mas é q é realmente unusual…[/quote]

O conceito de Usuaria, não é o conceito de usuario do sistema. São usuários de um serviço, e somente mulheres irão utiliza-lo.

Pois então, fazendo a associação @OneToOne não força você a deslocar os campos para Usuaria, vai continuar separado tanto nas classes qto nas tabelas.

Apesar de não estar escrito explicitamente composition ou embbeded o @OneToOne faz exatamente oq você quer.

Ou teria um dia estressante de trabalho interferido no meu raciocínio?

Colocando o @OneToOne, eu tenho que mapear o RegistroGeralUsuaria como uma entidade. Não queria isso,mas acredito ter o mesmo efeito que desejo com cascade=CascadeType.ALL e fetch=FetchType.EAGER. Eu só esperava que esse mapeamento fosse permitido.

Só queria compreender porque o Hibernate não permite fazer esse tipo de associação.

Valeu pela colaboração…

Consegui, depois de muito esforço, solucionar o problema…

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package entity;

import java.io.Serializable;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.AssociationOverride;
import javax.persistence.AssociationOverrides;
import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.UniqueConstraint;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.SecondaryTable;

/**
 *
 * @author helder
 */
@Entity
@Table(name = "Usuaria", uniqueConstraints = {
    @UniqueConstraint(columnNames = "CPF")})
@SecondaryTable(name = "RegistroGeralUsuaria", uniqueConstraints = @UniqueConstraint(columnNames = {"OrgaoExpedidorRG_id", "numero"}),
    pkJoinColumns=@PrimaryKeyJoinColumn(name="Usuaria_id"))
@NamedQueries(value = {
    @NamedQuery(name = "allUsuaria", query = "from Usuaria"),
    @NamedQuery(name = "loadUsuariaFromCPF", query = "from Usuaria where CPF like :cpf")
})
public class Usuaria implements Serializable {

    private static final long serialVersionUID = 1L;
    private Integer id;
    private String nome;
    private String CPF;
    private RegistroGeralUsuaria RG;
    private Date dataDeNascimento;
    private Set<String> telefones = new HashSet<String>();

    public Usuaria() {
    }

    @Id
    @GeneratedValue
    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    @Column(nullable = false, length = 60)
    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    @Column(name = "CPF", nullable = false, unique = true, length = 11)
    public String getCPF() {
        return CPF;
    }

    public void setCPF(String CPF) {
        this.CPF = CPF;
    }

    @Embedded
    @AttributeOverrides(value={
        @AttributeOverride(name="numero", column=@Column(name="numero", nullable=false, table="RegistroGeralUsuaria"))
    })
    @AssociationOverrides(value={
        @AssociationOverride(name="OrgaoExpedidorRG", joinColumns={@JoinColumn(name="OrgaoExpedidorRG", table="RegistroGeralUsuaria")})
    })
    public RegistroGeralUsuaria getRG() {
        return RG;
    }

    public void setRG(RegistroGeralUsuaria RG) {
        this.RG = RG;
        if (RG != null) {
            this.RG.setUsuaria(this);
        }
    }

    @Temporal(javax.persistence.TemporalType.DATE)
    @Column(nullable = false)
    public Date getDataDeNascimento() {
        return dataDeNascimento;
    }

    public void setDataDeNascimento(Date dataDeNascimento) {
        this.dataDeNascimento = dataDeNascimento;
    }

    @ElementCollection
    @CollectionTable(name = "Telefone", uniqueConstraints =
    @UniqueConstraint(columnNames = {"numero", "Usuaria_id"}))
    @Column(name = "numero", nullable = false, length = 11)
    public Set<String> getTelefones() {
        return telefones;
    }

    public void setTelefones(Set<String> telefones) {
        this.telefones = telefones;
    }

    public boolean addTelefone(String numero) {
        return this.telefones.add(numero);
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final Usuaria other = (Usuaria) obj;
        if ((this.CPF == null) ? (other.CPF != null) : !this.CPF.equals(other.CPF)) {
            return false;
        }
        return true;
    }

    @Override
    public int hashCode() {
        int hash = 5;
        hash = 79 * hash + (this.CPF != null ? this.CPF.hashCode() : 0);
        return hash;
    }
}