-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 7 posts ] 
Author Message
 Post subject: How to map a compositeID that contains a ForeignKey?
PostPosted: Mon Oct 15, 2007 4:10 pm 
Newbie

Joined: Tue Sep 11, 2007 12:17 pm
Posts: 9
Hi,

I have two tables in my database

KMS
-------
Instrument LONG (PrimaryKey)
------

RIMappings
----------------
Instrument LONG
FIELD_ID VARCHAR
--------------------


RIMappings consists of a compositeID of a foreignKey INSTRUMENT that references the KMS table and an assigned FIELD_ID.

An example of records in the database are as follows:
KMS:1
RIMappings:
1, BID
1, ASK
1, LAST


The issue that I have is that when I attempt to insert into the database, hibernate generates SQL Inserts that has a null value for the INSTRUMENT column in the RIMappings table.

In essence, what I am try to achieve over here is cascading the PrimaryKey of the KMS table (INSTRUMENT) to the compositeKey of the RIMappings table when I save the object.

My POJOS are defined as follows:

KMS.java
Code:
@Entity
@Table(schema="DBP", name="KMS")
public class KMS
{
private long instrument;
private Set<RIMappings> RIM=new HashSet<RIMappings>();

@Id
@GenericGenerator(name="seq_id",strategy="sequence",parameters={@Parameter(name="sequence",value="HIB_SEQ")}
@GeneratedValue(generator="seq_id")
public long getInstrument() {
      return instrument;
}
public void setInstrument(long instrument) {
   this.instrument = instrument;
}

@OneToMany(targetEntity=RIMappings.class,cascade=CascadeType.ALL)
@JoinColumn(name="INSTRUMENT")
public Set<RIMappings> getRIMappings()
{
   return RIM;
}
public void setRIMappings(Set<RIMappings> RIM)
{
   this.RIM=RIM;
}     
}



RIMappings.java
Code:
@Entity
@Table(schema="DBP", name="RIMappings")
@IdClass(RIMappingsId.class)
public class RIMappings {
   
private Long instrument;
private String fieldId;
private KMS kms;

@Id
@Column(name="INSTRUMENT", insertable=false, updatable=false, nullable=false)
public Long getInstrument() {
   return instrument;
}
public void setInstrument(Long instrument) {
   this.instrument = instrument;
}
   
   
@Id
@Column(name="FIELD_ID", nullable=false)
   public String getFieldId() {
      return fieldId;
   }
   public void setFieldId(String fieldId) {
      this.fieldId = fieldId;
   }
   
@ManyToOne(targetEntity = KMS.class)
@JoinColumn(name = "INSTRUMENT", nullable = false, insertable=false, updatable=false)
public KMS getKMS() {
      return kms;
   }

public void setKMS(KMS kms) {
      this.kms = kms;
   }

}


RIMappingsId.class
Code:
@Embeddable
public class RIMappingsId implements Serializable{
/**
*
*/
private static final long serialVersionUID = 7139311515487739123L;

private Long instrument;

private String fieldId;

@Column(name = "INSTRUMENT", nullable = false)
public Long getInstrument() {
   return this.instrument;
}

public void setInstrument(Long instrument) {
   this.instrument = instrument;
}

@Column(name = "FIELD_ID", nullable = false)
public String getFieldId() {
   return this.fieldId;
}
}


Top
 Profile  
 
 Post subject:
PostPosted: Wed Oct 17, 2007 4:13 am 
Newbie

Joined: Mon Oct 01, 2007 12:42 pm
Posts: 13
Location: Helsinki, Finland
In your case, field instrument is not needed in RIMappings since you already have @ManyToOne association with KMS. You also need the change KMS to be the owning side of the bidirectional association. Here are the changes that you need to make:

1) KMS.java:
- Change @OneToMany mapping to @OneToMany(mappedBy="kms",cascade=cascadeType.ALL)
- Remove @JoinColumn here


2) RIMappings.java
- Remove instrument field completely
- Annotate getKMS() with @Id and Remove @ManyToOne and @JoinColumn here


3) RIMappingsId.java
- Remove instrument field completely and replace it with:

@ManyToOne(targetEntity = KMS.class)
@JoinColumn(name = "INSTRUMENT", nullable = false)
public KMS getKMS() { ...}



I am struggling with the same kind of problem. I want the same kinf of primary and foreign keys, but I want to association on class level to be unidirectional so that the KMS would be the owning side. Does anyone know how this could be achieved?


Top
 Profile  
 
 Post subject:
PostPosted: Thu Oct 18, 2007 11:40 am 
Newbie

Joined: Tue Sep 11, 2007 12:17 pm
Posts: 9
Hi Immo,

Thanks a lot for your help! That seemed to have done the trick. However, in my hibernate logs I see two extra SELECT statements for RIMAPPINGS:
Code:
select
        rimappings_.INSTRUMENT,
                rimappings_.FIELD_ID
    from
        DB.RIMappings         rimappings_
    where
                rimappings_.INSTRUMENT=?
        and         rimappings_.FIELD_ID=?


My data-access code is as follows:
Code:
      KMS kms=new KMS();
     
      Set<RIMappings> rimsSet=new HashSet<RIMappings>();
     RIMappings rim1=new RIMappings();
     RIMappings rim2=new RIMappings();
     rim1.setKMS(kms);
     rim2.setKMS(kms);
     rim1.setFieldID("Field1");
     rim2.setFieldID("Field2");
    rimsSet.add(rim1);
    rimsSet.add(rim2);
   
   kms.setRIM(rimSet);
   getHibernateTemplate().save(kms);
     


Do you know why Hibernate is trying to fetch the records from the RIMappings before inserting?


Top
 Profile  
 
 Post subject:
PostPosted: Thu Oct 18, 2007 12:35 pm 
Newbie

Joined: Mon Oct 01, 2007 12:42 pm
Posts: 13
Location: Helsinki, Finland
No idea about the extra selects, I've been wondering about them too.

Can someone more experienced with Hibernate or someone from the development team explain the reason behing these selects?


Top
 Profile  
 
 Post subject:
PostPosted: Fri Feb 01, 2008 2:22 pm 
Beginner
Beginner

Joined: Tue Jan 08, 2008 2:15 pm
Posts: 22
I confirm I have the same extra select problem/question about them?


Top
 Profile  
 
 Post subject:
PostPosted: Fri Feb 01, 2008 2:24 pm 
Beginner
Beginner

Joined: Tue Jan 08, 2008 2:15 pm
Posts: 22
A work-around (I am not sure if there is no unwanted side-effect with it yet though), is to change the entity class so the parentId getter method obtains the parent id from the relation it has with it (in the first version of the entities above).


Top
 Profile  
 
 Post subject:
PostPosted: Fri Feb 01, 2008 3:28 pm 
Beginner
Beginner

Joined: Tue Jan 08, 2008 2:15 pm
Posts: 22
When cascading updates, even on a save(), HB has to know if child entities are new or old in order to save the graph the right way (updates, inserts). Since RIMappings has no generated Id or version field, HB checks in the 2nd level cache check and performs a select to find out if the entity row is not in the 2nd level cache. HB does not seem to cascade a save() to childs on save() on a parent, but a saveOrUpdate().


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 7 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.