tags:

views:

479

answers:

1

Hello,

I want to create a one to one mapping between the Entity Customer and OptIn. The OptIn Entity is optional. That is why the foreign key must be in OptIn. At deployment I get the following error because the mapping can not be found:

OneToOneSecondPass.java:135

Values: otherSide= optIn, mappedBy=customer

otherSideProperty = BinderHelper.findPropertyByName( otherSide, mappedBy );

java.lang.NullPointerException at org.hibernate.cfg.OneToOneSecondPass.doSecondPass(OneToOneSecondPass.java:135) at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1130) at org.hibernate.cfg.AnnotationConfiguration.secondPassCompile(AnnotationConfiguration.java:296) at org.hibernate.cfg.Configuration.buildMappings(Configuration.java:1115) ...

What can I do to get a correct mapping?

@Entity
@Table(name = "KPS_OPT_IN", schema = "EB")
public class OptIn extends KmsEntity implements java.io.Serializable {

    private static final long serialVersionUID = -8818445355079384264L;


    private int id; /* kps_kunden_nr */

    private Customer customer;  

    public OptIn() {
    }

    @Id
    @Column(name = "KPS_KUNDEN_NR", unique = true, nullable = false) 
    public int getId() {
     return this.id;
    }

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

    @OneToOne
    @PrimaryKeyJoinColumn(name="KPS_KUNDEN_NR", referencedColumnName="KPS_KUNDEN_NR") 
    public Customer getCustomer() {
     return customer;
    }

    public void setCustomer(Customer customer) {
        this.customer = customer;
        this.setId(customer.getId());
    }    
}


@Entity
@Table(name = "KPS_KUNDEN", schema = "EB")
public class Customer extends KmsEntity implements java.io.Serializable {

    private static final long serialVersionUID = 1L;

    private int id; 

    private OptIn optIn;

    public Customer() {
    }

    public Customer(int id) {
     this.id = id;
    }

    @Id
    @GeneratedValue(generator="seqkpskunde")
    @SequenceGenerator(name="seqkpskunde",sequenceName="SEQ_KPS_KUNDE") 
    @Column(name = "KPS_KUNDEN_NR", unique = true, nullable = false)
    public int getId() {
     return this.id;
    }

    public void setId(int id) {
     this.id = id;
     if(optIn!=null){
      optIn.setId(id);
     }
    }

    @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "customer")
    public OptIn getOptIn() {
     return optIn;
    }

    public void setOptIn(OptIn optIn) {
     this.optIn = optIn;
    }
}
A: 

I'm not sure what you mean by "foreign key must be in OptIn". You've mapped your @OneToOne association via @PrimaryKeyJoinColumn which means your entities will be linked via their ID values. It also means that:

  1. You can't specify column names within @PrimaryKeyJoinColumn annotation; they will be taken from appropriate @Id columns on both entities instead.
  2. Marking fetch as LAZY is pointless and going to be ignored; optional @OneToOne associations are always eagerly fetched.
  3. The only way OptIn would be optional on this association is if there was no entry with given ID in the database.

What Hibernate / Annotations versions are you using? If they're rather old it could be a bug in Hibernate code. But I believe it should work if you fix (1) and (2) above.

ChssPly76
Thank you very much so far. I will will try this tomorrow.Do you mean OptIn is only optional if the key/Id is in neither of both tables?
RainerB
Customer is the owner of this relationship. So if you have a Customer with pk=314 and OptIn with pk=314, the relationship will be there. If you don't have an OptIn with pk=314, `Customer.optIn` property will be NULL.
ChssPly76
Unfortunately I could not get it working if the id for the join is references from OptIn (mappedBy="customer"), only if I use the id in Customer. I am using hibernate 3.2.4sp1 and annotations 3.3.0GA. The solution with using the id from Customer is satisfactory for me.
RainerB
Sorry, I didn't quite understand your last comment. `mappedBy` is only applicable to FK-based associations (when you do it by PK, there's no association to maintain; it's implicit - thus specifying the "owner" end is pointless). The other end doesn't need to map anything at all. Look at the sample code here: http://docs.jboss.org/hibernate/stable/annotations/reference/en/html/entity.html#d0e1039
ChssPly76
Yes you are right. It is a legacy database where there are customer records without a corresponding optin record and I thought, the optin record could be made optional if the key in the optin record is used.I am now creating an optin record manually if it does not exist.
RainerB