13 Replies Latest reply on Jun 6, 2011 1:38 PM by Thiago Matos

    Problem in a OneToOne Relationship

    Luiz Soares Newbie

      I have an OneToOne relationship with two entities, one called PrecoContrato other called TipoServico. In these two entities I have the same object (that is a PK), that is cdTipoServico.


      My problem is that I can't make it work. I get the error: org.hibernate.AnnotationException: Unknown mappedBy in: org.domain.bl.entity.PmnPrecoContrato.pmnTipoServico, referenced property unknown: org.domain.bl.entity.PmnTipoServico.pmnPrecoContrato.


      Can somebody help me?


      I'll post the entities here:


      @Entity
      @Table(name = "PRECO_CONTRATO", schema = "BL_CORP_PRJ")
      public class PrecoContrato implements java.io.Serializable {
      
           private PrecoContratoId id;
           private BigDecimal vlUnidadeServico;
           private TipoServico tipoServico;
           
           public PrecoContrato() {
           }
      
           public PrecoContrato(PrecoContratoId id, BigDecimal vlUnidadeServico, TipoServico tipoServico) {
                this.id = id;
                this.vlUnidadeServico = vlUnidadeServico;
                this.setTipoServico(tipoServico);
           }
      
           @EmbeddedId
           @AttributeOverrides({
                     @AttributeOverride(name = "sqAquisicao", column = @Column(name = "SQ_AQUISICAO", nullable = false, precision = 10, scale = 0)),
                     @AttributeOverride(name = "cdTipoServico", column = @Column(name = "CD_TIPO_SERVICO", nullable = false, precision = 3, scale = 0)) })
           @NotNull
           public PrecoContratoId getId() {
                return this.id;
           }
      
           public void setId(PrecoContratoId id) {
                this.id = id;
           }
           
           @Column(name = "VL_UNIDADE_SERVICO", nullable = false, precision = 8)
           @NotNull
           public BigDecimal getVlUnidadeServico() {
                return this.vlUnidadeServico;
           }
      
           public void setVlUnidadeServico(BigDecimal vlUnidadeServico) {
                this.vlUnidadeServico = vlUnidadeServico;
           }
      
           @OneToOne(fetch = FetchType.LAZY, mappedBy="precoContrato")
           //@JoinColumn(name = "CD_TIPO_SERVICO", nullable = false, insertable = false, updatable = false)
           public TipoServico getTipoServico() {
                return tipoServico;
           }
           
           public void setTipoServico(TipoServico tipoServico) {
                this.tipoServico = tipoServico;
           }
      }




      NOTE: When I used Seam's Generate Entities, the PmnPrecoContrato wasn't here. I added it.

      @Embeddable
      public class PrecoContratoId implements java.io.Serializable {
      
           private long sqAquisicao;
           private short cdTipoServico;
      
           public PrecoContratoId() {
           }
      
           public PrecoContratoId(long sqAquisicao, short cdTipoServico) {
                this.sqAquisicao = sqAquisicao;
                this.cdTipoServico = cdTipoServico;
           }
      
           @Column(name = "SQ_AQUISICAO", nullable = false, precision = 10, scale = 0)
           public long getSqAquisicao() {
                return this.sqAquisicao;
           }
      
           public void setSqAquisicao(long sqAquisicao) {
                this.sqAquisicao = sqAquisicao;
           }
      
           @Column(name = "CD_TIPO_SERVICO", nullable = false, precision = 3, scale = 0)
           public short getCdTipoServico() {
                return this.cdTipoServico;
           }
      
           public void setCdTipoServico(short cdTipoServico) {
                this.cdTipoServico = cdTipoServico;
           }
      
           public boolean equals(Object other) {
                if ((this == other))
                     return true;
                if ((other == null))
                     return false;
                if (!(other instanceof PrecoContratoId))
                     return false;
                PrecoContratoId castOther = (PrecoContratoId) other;
      
                return (this.getSqAquisicao() == castOther.getSqAquisicao())
                          && (this.getCdTipoServico() == castOther.getCdTipoServico());
           }
      }



      Here goes the TipoServico Entity


      @Entity
      @Table(name = "TIPO_SERVICO", schema = "BL_CORP_PRJ")
      public class TipoServico implements java.io.Serializable {
      
           private short cdTipoServico;
           private String tpPeriodicidade;
           private String dsTipoServico;
           private PrecoContrato precoContrato;
      
           public TipoServico() {
           }
      
           public TipoServico(short cdTipoServico, String tpPeriodicidade,
                     String dsTipoServico, PrecoContrato precoContrato) {
                this.cdTipoServico = cdTipoServico;
                this.tpPeriodicidade = tpPeriodicidade;
                this.dsTipoServico = dsTipoServico;
                this.setPrecoContrato(precoContrato);
           }
      
           @Id
           @Column(name = "CD_TIPO_SERVICO", unique = true, nullable = false, precision = 3, scale = 0)
           public short getCdTipoServico() {
                return this.cdTipoServico;
           }
      
           public void setCdTipoServico(short cdTipoServico) {
                this.cdTipoServico = cdTipoServico;
           }
      
           @Column(name = "TP_PERIODICIDADE", nullable = false, length = 1)
           @NotNull
           @Length(max = 1)
           public String getTpPeriodicidade() {
                return this.tpPeriodicidade;
           }
      
           public void setTpPeriodicidade(String tpPeriodicidade) {
                this.tpPeriodicidade = tpPeriodicidade;
           }
      
           @Column(name = "DS_TIPO_SERVICO", nullable = false, length = 50)
           @NotNull
           @Length(max = 50)
           public String getDsTipoServico() {
                return this.dsTipoServico;
           }
      
           public void setDsTipoServico(String dsTipoServico) {
                this.dsTipoServico = dsTipoServico;
           }
           
           @OneToOne(fetch = FetchType.LAZY, mappedBy="tipoServico")
           //@JoinColumn(name = "CD_TIPO_SERVICO", nullable = false, insertable = false, updatable = false)
           public PrecoContrato getPrecoContrato() {
                return precoContrato;
           }
           
           public void setPrecoContrato(PrecoContrato precoContrato) {
                this.precoContrato = precoContrato;
           }
      }




      NOTE: The same thing here. I added this PrecoContrato after I generated the entity.
        • 1. Re: Problem in a OneToOne Relationship
          Tim Evers Master

          Your mapping could be wrong. I don't use OneToOne but looking at this example it would appear yours is not quite right.


          The example does not use the mappedBy on both sides of the @OneToOne. Maybe this will help?

          • 2. Re: Problem in a OneToOne Relationship
            Luiz Soares Newbie

            This way I posted was just a way that I tried. I don't know where the error is. I have another mappings that is very similar but the way I did them doesn't work on this one.


            Thanks for the example, was very good for learning but it didn't solve my problem.

            • 3. Re: Problem in a OneToOne Relationship
              Luiz Soares Newbie

              I have already used @PrimaryKeyJoinColumn, @JoinColumn. In the @OneToOne annotation I used targetEntity and mappedBy. None of these worked :(

              • 4. Re: Problem in a OneToOne Relationship
                Luiz Soares Newbie

                My error now is: broken column mapping for: tipoServico.id of: entity.PrecoContrato.

                • 5. Re: Problem in a OneToOne Relationship
                  Monkey Den Master

                  It surely will never work with the mapping annotation, @JoinColumn, commented out on both sides.  Use the @JoinColumn annotation on one side, mappedBy attribute of @OneToOne on the other.

                  • 6. Re: Problem in a OneToOne Relationship
                    Luiz Soares Newbie

                    Using mappedBy it gives me the first error (Unknown mappedBy in: org.domain.bl.entity.PmnPrecoContrato.pmnTipoServico, referenced property unknown: org.domain.bl.entity.PmnTipoServico.pmnPrecoContrato).


                    I'm using targetEntity.


                    I got something strange right now when I was trying to correct the mapping.
                    I put this on my TipoServico Entity:


                    @OneToOne(fetch=FetchType.LAZY, cascade=CascadeType.ALL, targetEntity=PmnPrecoContrato.class)
                         //@JoinColumn(name = "CD_TIPO_SERVICO", referencedColumnName = "CD_TIPO_SERVICO", insertable = false, updatable = false)
                         @OneToOne(fetch=FetchType.LAZY, cascade=CascadeType.ALL, targetEntity=PmnPrecoContrato.class)
                         @JoinColumn(name = "CD_TIPO_SERVICO", referencedColumnName = "CD_TIPO_SERVICO", insertable = false, updatable = false)
                         //@PrimaryKeyJoinColumn
                         public PmnPrecoContrato getPmnPrecoContrato() {
                              return pmnPrecoContrato;
                         }
                         
                         public void setPmnPrecoContrato(PmnPrecoContrato pmnPrecoContrato) {
                              this.pmnPrecoContrato = pmnPrecoContrato;
                         }
                         public PmnPrecoContrato getPmnPrecoContrato() {
                              return pmnPrecoContrato;
                         }
                         
                         public void setPmnPrecoContrato(PmnPrecoContrato pmnPrecoContrato) {
                              this.pmnPrecoContrato = pmnPrecoContrato;
                         }



                    And left my PrecoContrato Entity without the TipoServico values. Like this:


                    @Entity
                    @Table(name = "PRECO_CONTRATO", schema = "BL_CORP_PRJ")
                    public class PrecoContrato implements java.io.Serializable {
                    
                         private PrecoContratoId id;
                         private BigDecimal vlUnidadeServico;
                         private TipoServico tipoServico;
                         
                         public PrecoContrato() {
                         }
                    
                         public PrecoContrato(PrecoContratoId id, BigDecimal vlUnidadeServico, TipoServico tipoServico) {
                              this.id = id;
                              this.vlUnidadeServico = vlUnidadeServico;
                              this.setTipoServico(tipoServico);
                         }
                    
                         @EmbeddedId
                         @AttributeOverrides({
                                   @AttributeOverride(name = "sqAquisicao", column = @Column(name = "SQ_AQUISICAO", nullable = false, precision = 10, scale = 0)),
                                   @AttributeOverride(name = "cdTipoServico", column = @Column(name = "CD_TIPO_SERVICO", nullable = false, precision = 3, scale = 0)) })
                         @NotNull
                         public PrecoContratoId getId() {
                              return this.id;
                         }
                    
                         public void setId(PrecoContratoId id) {
                              this.id = id;
                         }
                         
                         @Column(name = "VL_UNIDADE_SERVICO", nullable = false, precision = 8)
                         @NotNull
                         public BigDecimal getVlUnidadeServico() {
                              return this.vlUnidadeServico;
                         }
                    
                         public void setVlUnidadeServico(BigDecimal vlUnidadeServico) {
                              this.vlUnidadeServico = vlUnidadeServico;
                         }



                    And it worked!
                    But, I don't know why, when I restarted the server, it gave me the broken column error but in the other hand, broken column mapping for: precoContrato.id of: entity.TipoServico.

                    • 7. Re: Problem in a OneToOne Relationship
                      Luiz Soares Newbie

                      It worked just that time. Now I'm getting all the same errors again. :(


                      • 8. Re: Problem in a OneToOne Relationship
                        Luiz Soares Newbie

                        I started reading about the OneToOne relationship and I got this as the correct way to do this specific relationship.


                        In PrecoContrato Entity:


                        @OneToOne(fetch=FetchType.LAZY, mappedBy="pmnPrecoContrato", cascade=CascadeType.ALL)
                             public TipoServico getTipoServico() {
                                  return tipoServico;
                             }
                             
                             public void setTipoServico(TipoServico tipoServico) {
                                  this.tipoServico = tipoServico;
                             }



                        In TipoServico Entity:


                        @OneToOne(fetch=FetchType.LAZY, cascade=CascadeType.ALL)
                             @JoinColumn(name = "CD_TIPO_SERVICO", referencedColumnName = "CD_TIPO_SERVICO", unique=true, nullable=false)
                             public PrecoContrato getPrecoContrato() {
                                  return precoContrato;
                             }
                             
                             public void setPrecoContrato(PrecoContrato precoContrato) {
                                  this.precoContrato = precoContrato;
                             }



                        I read that since the ForeignKey is in the PrecoContrato table, the mappedBy had to be in the PrecoContrato Entity to show that he is the end of the relationship and it is mapped in TipoServico Entity by the attribute precoContrato.


                        But, I still get this error: org.hibernate.MappingException: broken column mapping for: pmnTipoServico.id of: org.domain.bl.entity.PmnPrecoContrato


                        Can somebody help me?


                        NOTE: Since I have a composite-PK, Seam created an Id class in PrecoContrato Entity, the PrecoContratoId. It is in the first post.

                        • 9. Re: Problem in a OneToOne Relationship
                          Luiz Soares Newbie

                          I really need to solve this problem. Anyone can help me?

                          • 10. Re: Problem in a OneToOne Relationship
                            Val Sw Expert

                            Hi Luiz,


                            Was your problem solved ?, if so let what was the solution ?


                            I will try to implement the same soon.


                            Regards

                            • 11. Re: Problem in a OneToOne Relationship
                              Martin Frey Newbie

                              Hello guys.
                              I think this is really a hibernate related problem but anyway. If you have bidirectional relationships you need to set the relations in ypur code on both ends. I think this is what you are doing.
                              Secondly you need to persist both entities. Except if you use cascadetype correctly. You use just remove, so on delete hibernate will clean all related entities in this case. But on insert hibernate will do nothing. So you need to call persist on both instances. If one side defines notnull additionally you also have to take care of the order of the persist.


                              Try it and we see if this solves your issue.

                              • 12. Re: Problem in a OneToOne Relationship
                                Martin Frey Newbie

                                Ooops i've added me comment on the wrong thread... ignore it here please :)

                                • 13. Re: Problem in a OneToOne Relationship
                                  Thiago Matos Newbie

                                  In the file persistence.xml, add the path of your class.


                                  For example:


                                  <class>br.teste.entities.PrecoContrato</class>
                                  <class>br.teste.entities.TipoServico</class>