Недавно мы столкнулись с сложной ситуацией с отображением ассоциации гибернации с помощью составного поля идентификатора. Нам нужно было иметь двунаправленную связь с «один к одному» и «многие к одному». Наши таблицы буксировки были «REPORT» и «REPORT_SUMMARY», которые имеют отношение «один ко многим» от REPORT до REPORT_SUMMARY и отношение «многие к одному» от REPORT_SUMMARY в таблицу REPORT. Первичный ключ таблицы REPORT_SUMMARY определяется как составной первичный ключ, который состоит из поля идентификатора автоматического увеличения и первичного ключа таблицы REPORT.
|
1
2
3
4
5
|
CREATE TABLE REPORT ( ID INT(10) NOT NULL AUTO_INCREMENT, NAME VARCHAR(45) NOT NULL, PRIMARY KEY (`ID`)) ENGINE=InnoDB DEFAULT CHARSET=latin1; |
|
1
2
3
4
5
6
|
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; |
Спящие классы сущностей как пара.
Report.java
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
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
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
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;}@Overridepublic 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;}@Overridepublic 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
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
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;}@Overridepublic 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;}@Overridepublic 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; }} |
Объект отчета имеет коллекцию объектов ReportSummary, а ReportSummaryId имеет ссылку на объект Report. Самая важная часть этой реализации — это отображающие файлы в спящем режиме. Report.hbm.xml
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
|
<?xml version="1.0"?><!DOCTYPE hibernate-mapping PUBLIC"-//Hibernate/Hibernate Mapping DTD 3.0//EN"<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
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
|
<?xml version="1.0"?><!DOCTYPE hibernate-mapping PUBLIC"-//Hibernate/Hibernate Mapping DTD 3.0//EN"<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> |
Ссылка: Как использовать Hibernate для составных идентификаторов с сопоставлениями ассоциаций от нашего партнера JCG Семика Локу Калуге в блоге Code Box .