先使用映射文件映射自然复合主键实现一对多关联。
建表:student表和sc表分别如下所示:
student表:
sc表:
表之间的关系:student表存储学生记录,而sc表存储一个学生都有哪些课程。所以,Student与Sc是一对多关联,应该在Student.hbm.xml中配置与Sc的关联。
student表对应的映射文件Student.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"> <!-- Mapping file autogenerated by MyEclipse - Hibernate Tools --> <hibernate-mapping> <class name="org.shirdrn.entity.Student" table="student"> <id name="sno" type="java.lang.String" length="10"> <column name="sno" /> <generator class="assigned" /> </id> <property name="sname" type="java.lang.String"> <column name="sname" length="50" not-null="true" /> </property> <property name="dept" type="java.lang.String"> <column name="dept" length="50" /> </property> <set name="scs" table="sc" cascade="all" inverse="true"> <key> <column name="sno" not-null="true"></column> </key> <one-to-many class="org.shirdrn.entity.Sc"></one-to-many> </set> </class> </hibernate-mapping>
student表对应的POJO Student.java为:
package org.shirdrn.entity; import java.util.HashSet; import java.util.Set; /** * Student generated by MyEclipse - Hibernate Tools */ public class Student implements java.io.Serializable { private String sno; private String sname; private String dept; private Set scs = new HashSet(0); /** default constructor */ public Student() { } /** minimal constructor */ public Student(String sno, String sname) { this.sno = sno; this.sname = sname; } // Property accessors public String getSno() { return this.sno; } public void setSno(String sno) { this.sno = sno; } public String getSname() { return this.sname; } public void setSname(String sname) { this.sname = sname; } public String getDept() { return this.dept; } public void setDept(String dept) { this.dept = dept; } public Set getScs() { return scs; } public void setScs(Set scs) { this.scs = scs; } }
sc表对应的映射文件Sc.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"> <!-- Mapping file autogenerated by MyEclipse - Hibernate Tools --> <hibernate-mapping> <class name="org.shirdrn.entity.Sc" table="sc"> <composite-id> <key-property name="sno" type="java.lang.String"> <column name="sno" length="10" /> </key-property> <key-property name="cno" type="java.lang.String"> <column name="cno" length="10" /> </key-property> </composite-id> <property name="cname" type="java.lang.String"> <column name="cname" length="50" not-null="true" /> </property> <property name="score" type="java.lang.Integer"> <column name="score" not-null="true" /> </property> </class> </hibernate-mapping>
sc表对应的POJO文件Sc.java如下:
package org.shirdrn.entity; /** * Sc generated by MyEclipse - Hibernate Tools */ public class Sc implements java.io.Serializable { // Fields private String sno; private String cno; private String cname; private Integer score; // Constructors /** default constructor */ public Sc() { } /** full constructor */ public Sc(String sno, String cno, String cname, Integer score) { this.sno = sno; this.cno = cno; this.cname = cname; this.score = score; } // Property accessors public String getSno() { return this.sno; } public void setSno(String sno) { this.sno = sno; } public String getCno() { return this.cno; } public void setCno(String cno) { this.cno = cno; } public String getCname() { return this.cname; } public void setCname(String cname) { this.cname = cname; } public Integer getScore() { return this.score; } public void setScore(Integer score) { this.score = score; } public boolean equals(Object other) { if ((this == other)) return true; if ((other == null)) return false; if (!(other instanceof Sc)) return false; Sc castOther = (Sc) other; return ((this.getSno() == castOther.getSno()) || (this.getSno() != null && castOther.getSno() != null && this.getSno().equals( castOther.getSno()))) && ((this.getCno() == castOther.getCno()) || (this.getCno() != null && castOther.getCno() != null && this.getCno().equals( castOther.getCno()))); } public int hashCode() { int result = 17; result = 37 * result + (getSno() == null ? 0 : this.getSno().hashCode()); result = 37 * result + (getCno() == null ? 0 : this.getCno().hashCode()); return result; } }
因为Sc使用了复合主键,必须在对应的POJO类中重写hasCode()和equal()方法。
测试程序如下所示:
package org.shirdrn.test; import java.util.HashSet; import java.util.Set; import org.hibernate.Session; import org.hibernate.Transaction; import org.shirdrn.entity.Sc; import org.shirdrn.entity.Student; public class MyTest { public static void main(String[] args) { Session session = HibernateSessionFactory.getSession(); Transaction tx = null; try { tx = session.beginTransaction(); Student stu = new Student(); stu.setSno("200802001"); stu.setSname("孫權"); stu.setDept("class one"); Sc sc1 = new Sc(); sc1.setSno("200802001"); sc1.setCno("CS-001"); sc1.setCname("數據挖掘"); sc1.setScore(new Integer(95)); Sc sc2 = new Sc(); sc2.setSno("200802001"); sc2.setCno("CS-002"); sc2.setCname("搜索引擎"); sc2.setScore(new Integer(98)); Sc sc3 = new Sc(); sc3.setSno("200802001"); sc3.setCno("CS-003"); sc3.setCname("數據倉庫"); sc3.setScore(new Integer(88)); Set scs = new HashSet(); scs.add(sc1); scs.add(sc2); scs.add(sc3); stu.setScs(scs); session.save(stu); tx.commit(); } catch (Exception e) { tx.rollback(); e.printStackTrace(); } finally { HibernateSessionFactory.closeSession(); } } }
运行结果如下所示:
Hibernate: select sc_.sno, sc_.cno, sc_.cname as cname4_, sc_.score as score4_ from sc sc_ where sc_.sno=? and sc_.cno=?
Hibernate: select sc_.sno, sc_.cno, sc_.cname as cname4_, sc_.score as score4_ from sc sc_ where sc_.sno=? and sc_.cno=?
Hibernate: select sc_.sno, sc_.cno, sc_.cname as cname4_, sc_.score as score4_ from sc sc_ where sc_.sno=? and sc_.cno=?
Hibernate: insert into student (sname, dept, sno) values (?, ?, ?)
Hibernate: insert into sc (cname, score, sno, cno) values (?, ?, ?, ?)
Hibernate: insert into sc (cname, score, sno, cno) values (?, ?, ?, ?)
Hibernate: insert into sc (cname, score, sno, cno) values (?, ?, ?, ?)
在存储一个学生记录的同时,向sc表中插入对应于这个学生的三条课程的记录。