Recently, We faced a tricky situation with hibernate association mapping with a composite id field. We needed to have bidirectional association with one-to-may and many-to-one.Our tow tables was "REPORT" and "REPORT_SUMMARY" which has one-to-many relationship from REPORT to REPORT_SUMMARY and many-to-one relationship from REPORT_SUMMARY to REPORT table. The primary key of REPORT_SUMMARY table is defined as a composite primary key which consists of auto increment id field and the primary key of REPORT table.
CREATE TABLE REPORT ( ID INT(10) NOT NULL AUTO_INCREMENT, NAME VARCHAR(45) NOT NULL, PRIMARY KEY (`ID`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE REPORT_SUMMARY ( ID INT(10) NOT NULL AUTO_INCREMENT, NAME VARCHAR(45) NOT NULL, RPT_ID INT(10) NOT NULL, PRIMARY KEY (`ID`,`RPT_ID`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
The hibernate entity classes are as fallows.
Report.java
package com.semika.autoac.entities; import java.io.Serializable; import java.util.HashSet; import java.util.Set; public class Report implements Serializable{ private static final long serialVersionUID = 9146156921169669644L; private Integer id; private String name; private Set<ReportSummary> reportSummaryList = new HashSet<ReportSummary>(); public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Set<ReportSummary> getReportSummaryList() { return reportSummaryList; } public void setReportSummaryList(Set<ReportSummary> reportSummaryList) { this.reportSummaryList = reportSummaryList; } }
ReportSummary.java
package com.semika.autoac.entities; import java.io.Serializable; public class ReportSummary implements Serializable { private static final long serialVersionUID = 8052962961003467437L; private ReportSummaryId id; private String name; public ReportSummaryId getId() { return id; } public void setId(ReportSummaryId id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((id == null) ? 0 : id.hashCode()); result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; ReportSummary other = (ReportSummary) obj; if (id == null) { if (other.id != null) return false; } else if (!id.equals(other.id)) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } }
ReportSummaryId.java
package com.semika.autoac.entities; import java.io.Serializable; public class ReportSummaryId implements Serializable{ private static final long serialVersionUID = 6911616314813390449L; private Integer id; private Report report; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Report getReport() { return report; } public void setReport(Report report) { this.report = report; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((id == null) ? 0 : id.hashCode()); result = prime * result + ((report == null) ? 0 : report.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; ReportSummaryId other = (ReportSummaryId) obj; if (id == null) { if (other.id != null) return false; } else if (!id.equals(other.id)) return false; if (report == null) { if (other.report != null) return false; } else if (!report.equals(other.report)) return false; return true; } }
Report object has a collection of ReportSummary objects and ReportSummaryId has a reference to Report object.
The most important part of this implementation is hibernate mapping files.
Report.hbm.xml
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.semika.autoac.entities.Report" table="REPORT" > <id name="id" type="int" column="id" > <generator class="native"/> </id> <property name="name"> <column name="NAME" /> </property> <set name="reportSummaryList" table="REPORT_SUMMARY" cascade="all" inverse="true"> <key column="RPT_ID" not-null="true"></key> <one-to-many class="com.semika.autoac.entities.ReportSummary"/> </set> </class> </hibernate-mapping>
ReportSummary.hbm.xml
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.semika.autoac.entities.ReportSummary" table="REPORT_SUMMARY" > <composite-id name="id" class="com.semika.autoac.entities.ReportSummaryId"> <key-property name="id" column="ID"></key-property> <key-many-to-one name="report" class="com.semika.autoac.entities.Report" column="RPT_ID"</key-many-to-one> </composite-id> <property name="name"> <column name="NAME" /> </property> </class> </hibernate-mapping>
0 comments:
Post a Comment