-->
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.  [ 16 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Problem with composite keys.
PostPosted: Wed May 12, 2004 5:12 am 
Regular
Regular

Joined: Tue May 11, 2004 9:23 am
Posts: 69
Hi,

I got a problem with composite keys. I have two tables Customer and Country. The relation between them are Many-To-One.

Country
...........
countryCode (PK)
countryName

Customer
.............
countryCode (FK)
customerNo (PK)
...

Both countryCode and customerNo are together a composite key in Customer.

The problem I get is when Hibernate is trying to map. It complains on not finding the field CompID . See the fault below.

net.sf.hibernate.PropertyNotFoundException: field not found: CompID
at net.sf.hibernate.property.DirectPropertyAccessor.getField(DirectPropertyAccessor.java:74)
at net.sf.hibernate.property.DirectPropertyAccessor.getField(DirectPropertyAccessor.java:80)
at net.sf.hibernate.property.DirectPropertyAccessor.getGetter(DirectPropertyAccessor.java:88)
at net.sf.hibernate.util.ReflectHelper.getter(ReflectHelper.java:65)
at net.sf.hibernate.util.ReflectHelper.reflectedPropertyClass(ReflectHelper.java:74)
at net.sf.hibernate.cfg.Binder.bindRootClass(Binder.java:285)
at net.sf.hibernate.cfg.Binder.bindRoot(Binder.java:1229)
at net.sf.hibernate.cfg.Configuration.add(Configuration.java:249)
at net.sf.hibernate.cfg.Configuration.addInputStream(Configuration.java:285)
at net.sf.hibernate.cfg.Configuration.addClass(Configuration.java:333)
at net.sf.hibernate.TestCustomerCountry.configure(TestCustomerCountry.java:28)
at net.sf.hibernate.TestCustomerCountry.main(TestCustomerCountry.java:117)



I've understood that with composite keys hibernate needs a component as I understood an extra java class containing these keys or am I wrong? I didn't understand exactly how to use it.

Anyway below is my code and I hope that someone could see what I'm doing wrong in the XML mapping file and help me correct it.


------------
Country
------------
package net.sf.hibernate;
public class Country{
private String countryName;
private String countryCode;



/**
* Returns the countryCode.
* @return String
*/
public String getCountryCode() {
return countryCode;
}

/**
* Returns the countryName.
* @return String
*/
public String getCountryName() {
return countryName;
}

/**
* Sets the countryCode.
* @param countryCode The countryCode to set
*/
public void setCountryCode(String countryCode) {
this.countryCode = countryCode;
}

/**
* Sets the countryName.
* @param countryName The countryName to set
*/
public void setCountryName(String countryName) {
this.countryName = countryName;
}

}


----------------
Customer
----------------

package net.sf.hibernate;
public class Customer{
private String customerNo;
private Country countryCode;
private String firstName;
private String lastName;
private String street;
private String zipcode;
private String co_address;
private String city;
private String state;
private String phoneNo;
private int versionNo;



/**
* Returns the city.
* @return String
*/
public String getCity() {
return city;
}

/**
* Returns the co_address.
* @return String
*/
public String getCo_address() {
return co_address;
}

/**
* Returns the countryCode.
* @return Country
*/
public Country getCountryCode() {
return countryCode;
}

/**
* Returns the customerNo.
* @return String
*/
public String getCustomerNo() {
return customerNo;
}

/**
* Returns the firstName.
* @return String
*/
public String getFirstName() {
return firstName;
}

/**
* Returns the lastName.
* @return String
*/
public String getLastName() {
return lastName;
}

/**
* Returns the phoneNo.
* @return String
*/
public String getPhoneNo() {
return phoneNo;
}

/**
* Returns the state.
* @return String
*/
public String getState() {
return state;
}

/**
* Returns the street.
* @return String
*/
public String getStreet() {
return street;
}

/**
* Returns the versionNo.
* @return int
*/
public int getVersionNo() {
return versionNo;
}

/**
* Returns the zipcode.
* @return String
*/
public String getZipcode() {
return zipcode;
}

/**
* Sets the city.
* @param city The city to set
*/
public void setCity(String city) {
this.city = city;
}

/**
* Sets the co_address.
* @param co_address The co_address to set
*/
public void setCo_address(String co_address) {
this.co_address = co_address;
}

/**
* Sets the countryCode.
* @param countryCode The countryCode to set
*/
public void setCountryCode(Country countryCode) {
this.countryCode = countryCode;
}

/**
* Sets the customerNo.
* @param customerNo The customerNo to set
*/
public void setCustomerNo(String customerNo) {
this.customerNo = customerNo;
}

/**
* Sets the firstName.
* @param firstName The firstName to set
*/
public void setFirstName(String firstName) {
this.firstName = firstName;
}

/**
* Sets the lastName.
* @param lastName The lastName to set
*/
public void setLastName(String lastName) {
this.lastName = lastName;
}

/**
* Sets the phoneNo.
* @param phoneNo The phoneNo to set
*/
public void setPhoneNo(String phoneNo) {
this.phoneNo = phoneNo;
}

/**
* Sets the state.
* @param state The state to set
*/
public void setState(String state) {
this.state = state;
}

/**
* Sets the street.
* @param street The street to set
*/
public void setStreet(String street) {
this.street = street;
}

/**
* Sets the versionNo.
* @param versionNo The versionNo to set
*/
public void setVersionNo(int versionNo) {
this.versionNo = versionNo;
}

/**
* Sets the zipcode.
* @param zipcode The zipcode to set
*/
public void setZipcode(String zipcode) {
this.zipcode = zipcode;
}

}


---------------------------------------
Extra table for the composite keys
---------------------------------------

package net.sf.hibernate;
import java.io.Serializable;

public class CompositeCustCounID{
private Country countryCode;
private Customer customerNo;


/**
* Returns the countryCode.
* @return Country
*/
public Country getCountryCode() {
return countryCode;
}

/**
* Returns the customerNo.
* @return Customer
*/
public Customer getCustomerNo() {
return customerNo;
}

/**
* Sets the countryCode.
* @param countryCode The countryCode to set
*/
public void setCountryCode(Country countryCode) {
this.countryCode = countryCode;
}

/**
* Sets the customerNo.
* @param customerNo The customerNo to set
*/
public void setCustomerNo(Customer customerNo) {
this.customerNo = customerNo;
}

}


------------------------------------
the XML mapping file
------------------------------------

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">

<hibernate-mapping>
<class name="net.sf.hibernate.Customer" table="CUSTOMER_T">
<composite-id name="CompID" class="net.sf.hibernate.CompositeCustCounID">
<key-property name="customerNo" column="CUSTOMERNO"/>
<key-many-to-one name="countryCode" column="COUNTRYCODE" class="net.sf.hibernate.Country"/>
</composite-id>

<property name="city" column="CITY"/>
<property name="co_address" column="CO_ADDRESS"/>
<property name="firstName" column="FIRSTNAME"/>
<property name="lastName" column="LASTNAME"/>
<property name="phoneNo" column="PHONENO"/>
<property name="state" column="STATE"/>
<property name="street" column="STREET"/>
<property name="versionNo" column="VERSIONNO"/>
<property name="zipcode" column="ZIPCODE"/>
</class>

</hibernate-mapping>
<!-- parsed in 0ms -->




Best regards

Johan


Top
 Profile  
 
 Post subject:
PostPosted: Wed May 12, 2004 5:14 am 
Regular
Regular

Joined: Tue May 11, 2004 9:23 am
Posts: 69
Here's the XML-file for Country too:


<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">

<hibernate-mapping>
<class name="net.sf.hibernate.Country" table="COUNTRY_T">
<id name="countryCode" column="COUNTRYCODE">
<generator class="assigned"/>
</id>
<property name="countryName" column="COUNTRYNAME"/>
</class>

</hibernate-mapping>
<!-- parsed in 16ms -->


Top
 Profile  
 
 Post subject:
PostPosted: Wed May 12, 2004 9:46 am 
Hibernate Team
Hibernate Team

Joined: Thu Dec 18, 2003 9:55 am
Posts: 1977
Location: France
package net.sf.hibernate;
public class Customer{
//private String customerNo;
//private Country countryCode;
private CompositeCustCounID compID;
private String firstName;
private String lastName;
private String street;
private String zipcode;
private String co_address;
private String city;
private String state;
private String phoneNo;
private int versionNo;
....


don't forget implements Serializable + equals/hashcode as explained in the doc


Top
 Profile  
 
 Post subject:
PostPosted: Wed May 12, 2004 11:20 am 
Expert
Expert

Joined: Fri Feb 06, 2004 7:49 am
Posts: 255
Location: Moscow, Russia
Remove name="CompID" from the following mapping:
Code:
<composite-id name="CompID" class="net.sf.hibernate.CompositeCustCounID">
  <key-property name="customerNo" column="CUSTOMERNO"/>
  <key-many-to-one name="countryCode" column="COUNTRYCODE" class="net.sf.hibernate.Country"/>
</composite-id>


you need name attribute for composite-id element only when you want to map your composite id into some component
7.4. Components as composite identifiers http://www.hibernate.org/hib_docs/reference/en/html/components.html#components-compositeid


Top
 Profile  
 
 Post subject:
PostPosted: Wed May 12, 2004 11:25 am 
Expert
Expert

Joined: Fri Feb 06, 2004 7:49 am
Posts: 255
Location: Moscow, Russia
shl wrote:
Remove name="CompID" from the following mapping:
and remove class attrbiute, or use approach that delpouve suggested to you read the chapter 7.4. Components as composite identifiers


Top
 Profile  
 
 Post subject:
PostPosted: Wed May 12, 2004 11:38 am 
Hibernate Team
Hibernate Team

Joined: Thu Dec 18, 2003 9:55 am
Posts: 1977
Location: France
Quote:
you need name attribute for composite-id element only when you want to map your composite id into some component


it's also a king of "best practice" to use such a component to manage composite id, it's adviced to use it


Top
 Profile  
 
 Post subject:
PostPosted: Wed May 12, 2004 11:54 am 
Expert
Expert

Joined: Fri Feb 06, 2004 7:49 am
Posts: 255
Location: Moscow, Russia
Yes, delpouve is right,
in my previous post I wanted to say that if you removed name attribute you should remove class attribute too.


Top
 Profile  
 
 Post subject:
PostPosted: Wed May 12, 2004 12:01 pm 
Expert
Expert

Joined: Fri Feb 06, 2004 7:49 am
Posts: 255
Location: Moscow, Russia
Johan,

There are some useful links about composite-id http://forum.hibernate.org/viewtopic.php?t=928990


Top
 Profile  
 
 Post subject:
PostPosted: Thu May 13, 2004 4:05 am 
Regular
Regular

Joined: Tue May 11, 2004 9:23 am
Posts: 69
Hey again guys,

Thanks for clearing it up,

The mapping works fine write now, though I have a new problem which have come-up (I'm not suprised =)). Get the following fault:

could not resolve property: countryCode of: net.sf.hibernate.Customer [SELECT co.countryName, cu.firstName FROM net.sf.hibernate.Country co, net.sf.hibernate.Customer cu WHERE co.countryCode=cu.countryCode]

I'm thinking that I have mapped the countryCode wrong. Right now I have javaclass with the composite keys and the XML-file looks like this.

<hibernate-mapping>
<class name="net.sf.hibernate.CompositeCustCounID" table="COMPOSITECUSTCOUNID_T">
<composite-id>
[color=red]<key-many-to-one name="countryCode" column="COUNTRYCODE" class="net.sf.hibernate.Country"/>

<key-property name="customerNo" column="CUSTOMERNO" type="string"/>
</composite-id>
</class>

</hibernate-mapping>[/color]

Is it wrong to use <key-many-to-one> tag (I'm getting countryCode from another table in the database so I thougnt this is the one).

What do I do? I don't know how to fix the problem.

Best regs Johan.


Top
 Profile  
 
 Post subject:
PostPosted: Thu May 13, 2004 4:09 am 
Hibernate Team
Hibernate Team

Joined: Thu Dec 18, 2003 9:55 am
Posts: 1977
Location: France
SELECT cu.country.countryName, cu.firstName FROM net.sf.hibernate.Customer cu


Top
 Profile  
 
 Post subject:
PostPosted: Thu May 13, 2004 4:15 am 
Expert
Expert

Joined: Fri Feb 06, 2004 7:49 am
Posts: 255
Location: Moscow, Russia
new_man wrote:
SELECT co.countryName, cu.firstName FROM net.sf.hibernate.Country co, net.sf.hibernate.Customer cu WHERE co.countryCode=cu.countryCode


access to all parts of your composite-id keys (countryCode, customerNo) vi id prefix (id.countryCode, id.customerNo), use the following HQL:
Code:
SELECT co.countryName, cu.firstName FROM net.sf.hibernate.Country co, net.sf.hibernate.Customer cu WHERE co.id.countryCode=cu.id.countryCode


Top
 Profile  
 
 Post subject:
PostPosted: Thu May 13, 2004 4:27 am 
Regular
Regular

Joined: Tue May 11, 2004 9:23 am
Posts: 69
Quote:
access to all parts of your composite-id keys (countryCode, customerNo) vi id prefix (id.countryCode, id.customerNo), use the following HQL:
SELECT co.countryName, cu.firstName FROM net.sf.hibernate.Country co, net.sf.hibernate.Customer cu WHERE co.id.countryCode=cu.id.countryCode



Tried it though get "dereferenced" as fault:

net.sf.hibernate.QueryException: dereferenced: country0_.id.countryCode [SELECT co.countryName, cu.firstName FROM net.sf.hibernate.Country co, net.sf.hibernate.Customer cu, net.sf.hibernate.Customer cu WHERE co.id.countryCode=cu.id.countryCode]

countryCode can be found i Customer.hbm.xml but not in the Customer.java since it's a foreign key. I tried to redirect it so the countryCode would be "taken" from the keyclass "CompositeCustCounID" but didn't work.

Br. Johan


Top
 Profile  
 
 Post subject:
PostPosted: Thu May 13, 2004 4:36 am 
Regular
Regular

Joined: Tue May 11, 2004 9:23 am
Posts: 69
What does it mean with dereferenced? Can it be that I've mapped wrong? (Even though) it's working?


Top
 Profile  
 
 Post subject:
PostPosted: Thu May 13, 2004 6:27 am 
Expert
Expert

Joined: Fri Feb 06, 2004 7:49 am
Posts: 255
Location: Moscow, Russia
new_man wrote:
net.sf.hibernate.QueryException: dereferenced: country0_.id.countryCode [SELECT co.countryName, cu.firstName FROM net.sf.hibernate.Country co, net.sf.hibernate.Customer cu, net.sf.hibernate.Customer cu WHERE co.id.countryCode=cu.id.countryCode]


There was a error in my previous HQL query, try this:
Code:
SELECT co.countryName, cu.firstName FROM net.sf.hibernate.Country co, net.sf.hibernate.Customer cu WHERE co.countryCode=cu.id.countryCode


You can access all parts of composite-id via "id." prefix, but as I got countryCode in Country class is not a part of composite-id.


Top
 Profile  
 
 Post subject:
PostPosted: Thu May 13, 2004 6:30 am 
Expert
Expert

Joined: Fri Feb 06, 2004 7:49 am
Posts: 255
Location: Moscow, Russia
countryCode in Country class is an ID, than the following HQL query is correct to:
Code:
SELECT co.countryName, cu.firstName FROM net.sf.hibernate.Country co, net.sf.hibernate.Customer cu WHERE co.id=cu.id.countryCode


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 16 posts ]  Go to page 1, 2  Next

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.