Need help with Hibernate? Read this first:
http://www.hibernate.org/ForumMailingli ... AskForHelp
I am facing problems with many-to-many relationship in tables where the relation table has an attribute other than the composite primary key. I am using Spring 1.2 ORM package for hibernate. Things are fine when the relation table contains only the composite key. The hibernate documentation also talks about the same; I could not gather any information to validate whether my mapping is correct or not.
The details are:
Hibernate version: 3.0
Mapping documents:
Customer.hbm
<hibernate-mapping >
<class name="model.Customer" table="CUSTOMER">
<id name="Id" type="integer" column="CUST_ID">
<generator class="increment"/>
</id>
<property name="FirstName" column="FIRST_NAME" type="string" not-null="true" length="50"/>
...
<property name="SecurityAnswer" column="SECURITY_ANSWER" type="string" not-null="true" length="100"/>
<set name="AdditionalRequirements" table="CUST_ADDITIONAL_REQUIREMENTS" cascade="all">
<key column="CUST_ID"/>
<many-to-many column="QUESTION_ID" class="model.AdditionalRequirements"/>
</set>
</class>
</hibernate-mapping>
AdditionalRequirements.hbm
<hibernate-mapping >
<class name="model.AdditionalRequirements" table="ADDITIONAL_REQUIREMENTS" >
<id name="Id" type="integer" column="QUESTION_ID">
<generator class="increment"/>
</id>
...
<set name="CUSTOMERs" table="CUST_ADDITIONAL_REQUIREMENTS" cascade="all">
<key column="QUESTION_ID"/>
<many-to-many column="CUST_ID" class="model.Customer"/>
</set>
</class>
</hibernate-mapping>
CustAdditionalRequirements.hbm
<hibernate-mapping>
<class name="model.CustAdditionalRequirements" table="CUST_ADDITIONAL_REQUIREMENTS">
<composite-id name="Id" class="model.CustAdditionalRequirementsPK">
<key-many-to-one name="Question" class="model.AdditionalRequirements"
column="QUESTION_ID" />
<key-many-to-one name="Cust" class="model.Customer" column="CUST_ID"/>
</composite-id>
<property name="Answer" column="ANSWER" type="string" not-null="false" length="1000"/>
</class>
</hibernate-mapping>
Code between sessionFactory.openSession() and session.close():
public class CustomerDAOImpl extends HibernateDaoSupport implements CustomerDAO {
public java.lang.Integer save(model.Customer customer)
throws org.hibernate.HibernateException {
System.out.println("inside save");
return (java.lang.Integer)this.getHibernateTemplate().save((Object) customer);
}
Full stack trace of any exception that occurs:
org.springframework.orm.hibernate3.HibernateSystemException: IllegalArgumentException occurred calling getter of model.AdditionalRequirements.Id; nested exception is org.hibernate.PropertyAccessException: IllegalArgumentException occurred calling getter of model.AdditionalRequirements.Id
org.hibernate.PropertyAccessException: IllegalArgumentException occurred calling getter of model.AdditionalRequirements.Id
Name and version of the database you are using:
MySQL 4.1
The generated SQL (show_sql=true):
No SQL shown on console though show_sql=true
Debug level Hibernate log excerpt:
Other relevant information:
The table DDL are:
CREATE TABLE `additional_requirements` ( `QUESTION_ID` decimal(4,0) NOT NULL default '0', `QUESTION_DESC` text NOT NULL, `QUESTION_STATUS` char(1) default NULL, PRIMARY KEY (`QUESTION_ID`) )
CREATE TABLE `customer` ( `CUST_ID` decimal(12,0) NOT NULL default '0', `FIRST_NAME` varchar(50) NOT NULL default '', `LAST_NAME` varchar(50) NOT NULL default '', ...
PRIMARY KEY (`CUST_ID`) )
CREATE TABLE `cust_additional_requirements` ( `cust_id` decimal(12,0) NOT NULL default '0', `question_id` decimal(4,0) NOT NULL default '0', `answer` text, PRIMARY KEY (`cust_id`,`question_id`), KEY `CUST_ADDITIONAL_REQ_FK1` (`question_id`), KEY `CUST_ADDITIONAL_REQ_FK2` (`cust_id`), CONSTRAINT `CUST_ADDITIONAL_REQ_FK2` FOREIGN KEY (`cust_id`) REFERENCES `customer` (`CUST_ID`), CONSTRAINT `CUST_ADDITIONAL_REQ_FK1` FOREIGN KEY (`question_id`) REFERENCES `additional_requirements` (`QUESTION_ID`) )
POJO used
3 POJOs are being used i.e. Customer.java, CustAdditionalRequirements.java, AdditionalRequirements.java wherein the relationships are as follows:
Customer has private java.util.Set additionalRequirements; variable
AdditionalRequirements has: // collections private java.util.Set cUSTOMERs;
CustAdditionalRequirements has
// primary key
private model.CustAdditionalRequirementsPK id;
// fields
private java.lang.String answer;
where CustAdditionalRequirementsPK has
private model.AdditionalRequirements question;
private model.Customer cust;
The test program is:
/*
* Test method
*/
public final void testSave() {
// TODO Auto-generated method stub
try {
FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext("E:\\springapp-servlet.xml");
BeanFactory bf = context.getBeanFactory();
CustomerDAO custDao = (CustomerDAO) bf.getBean("iCustomerDao");
Set customers = new HashSet();
Customer cust = new Customer(null, null, "abc", "XYZ","JKS",...,"answer");
Integer custNbr = custDao.save(cust);
AdditionalRequirements additionalRequirements = new AdditionalRequirements();
additionalRequirements.setId(new Integer(1));
additionalRequirements.setQuestionDesc("Question1");
additionalRequirements.setQuestionStatus("A");
CustAdditionalRequirementsPK custAdditionalRequirementsPK = new CustAdditionalRequirementsPK();
custAdditionalRequirementsPK.setQuestionId(new Integer(1));
custAdditionalRequirementsPK.setCustId(custNbr);
CustAdditionalRequirements custAdditionalRequirements = new CustAdditionalRequirements();
custAdditionalRequirements.setId(custAdditionalRequirementsPK);
custAdditionalRequirements.setAnswer("Yes");
cust.addToAdditionalRequirements(additionalRequirements);
custDao.saveOrUpdate(cust);
}catch(Exception e) {
e.printStackTrace();
}
}