俗話說,本身寫的代碼,6個月後也是別人的代碼……複習!複習!複習!涉及的知識點總結以下:java
多對一單向外鍵關聯關係數據庫
注意多對一關聯是多方持有一方的引用。看一個例子,去淘寶購物,那麼一個淘寶用戶能夠對應多個購物訂單,如圖所示:緩存
多的一方是Orders,持有一方的引用,也就是Users,而在Users中無需做任何定義,從訂單到用戶的關係是單向多對一關聯。對應數據庫就是:session
還有好比說學生和班級的關係,多個學生能夠屬於同一個班級,這就是從學生到班級也是典型的單向多對一關係,看代碼實現:架構
基於註解的多對一單向外鍵關聯:併發
單向多對一關聯中,多方須要持有一方的引用,那麼多方(學生類)須要額外配置,須要對持有的一方引用使用註解@ManyToOne (cascade={CascadeType.ALL}, fetch=FetchType.EAGER),設置爲級聯操做和飢渴的抓取策略,@JoinColumn(name="cid"),而一方(教室類)無需作任何多方的定義。app
注意;多方必須保留一個不帶參數的構造器!框架
import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; //班級類,在多對一關係中屬於一的方,不持有其餘多餘的配置,反而是被多方持有 @Entity public class ClassRoom { private int cid;//班級編號 private String cname;//班級名稱 // 自動增加的主鍵 @Id @GeneratedValue public int getCid() { return cid; } public void setCid(int cid) { this.cid = cid; } public String getCname() { return cname; } public void setCname(String cname) { this.cname = cname; } }
一方——班級類無需作多餘的定義,下面是多方——學生實體和配置:ide
import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; //學生實體類,屬於多對一的多方,持有班級(一方)的引用 @Entity public class Students { private int sid; //編號 private String sname; //姓名 private ClassRoom classroom;//學生班級 //注意:多方必定要顯式的定義不帶參數的構造方法 public Students() { } public Students(String sname) { this.sname = sname; } // 多方使用註解:@ManyToOne // fetch=FetchType.EAGER,急加載,加載一個實體時,定義急加載的屬性會當即從數據庫中加載。 // 所有級聯操做,referencedColumnName顯式設置數據庫字段名cid,不寫默認就是和name同樣的。 @ManyToOne (cascade={CascadeType.ALL}, fetch=FetchType.EAGER) @JoinColumn(name="cid",referencedColumnName="cid") public ClassRoom getClassroom() { return classroom; } public void setClassroom(ClassRoom classroom) { this.classroom = classroom; } // 自動增加主鍵 @Id @GeneratedValue public int getSid() { return sid; } public void setSid(int sid) { this.sid = sid; } public String getSname() { return sname; } public void setSname(String sname) { this.sname = sname; } }
下面測試:先生成數據庫腳本,再進行學生對象的插入性能
public class TestStudentsByAnno { private static SessionFactory sessionFactory; @Before public void setUp() throws Exception { System.out.println("setUp()..."); sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory(); } @After public void tearDown() throws Exception { System.out.println("tearDown()..."); sessionFactory.close(); } @Test public void testSave() { Session session = sessionFactory.getCurrentSession(); Transaction tx = session.beginTransaction(); try { ClassRoom c = new ClassRoom(); c.setCname("computer001"); Students s = new Students("zhangsan"); s.setClassroom(c); session.save(s); tx.commit(); } catch(Exception ex) { ex.printStackTrace(); tx.rollback(); } } @Test @Ignore public void testSchemaExport() { SchemaExport se = new SchemaExport(new AnnotationConfiguration().configure()); se.create(true, true); } }
反向建立表的數據庫腳本以下:
create table ClassRoom (cid integer not null auto_increment, cname varchar(255), primary key (cid))
create table Students (sid integer not null auto_increment, sname varchar(255), cid integer, primary key (sid))
插入一個學生對象,會自動生成以下語句:
ClassRoom c = new ClassRoom(); c.setCname("computer001"); Students s = new Students("zhangsan"); s.setClassroom(c); session.save(s); tx.commit();
Hibernate: insert into ClassRoom (cname) values (?)
Hibernate: insert into Students (cid, sname) values (?, ?)
插入成功:
基於xml配置實現多對一單向外鍵關聯
<hibernate-mapping> <class name="net.nw.vo.fk.mto.ClassRoom" table="classroom"> <id name="cid" column="cid" type="int"> <generator class="native"/> </id> <property name="cname" column="cname" type="string"/> </class> </hibernate-mapping>
一方(教室類)無需作任何多方的定義。只須要維護好本身的屬性配置便可。而多方只須要加上<many-to-one name="" column=「"/>就ok。
<hibernate-mapping> <class name="net.nw.vo.fk.mto.Students" table="students"> <id name="sid" column="sid" type="int"> <generator class="native"/> </id> <property name="sname" column="sname" type="string"/> <many-to-one name="classroom" column="cid"/> </class> </hibernate-mapping>
hibernate.cfg.xml里加上
<mapping resource="net/nw/vo/fk/mto/ClassRoom.hbm.xml" /> <mapping resource="net/nw/vo/fk/mto/Students.hbm.xml" />
注意:若是沒有設置級聯ALL,那麼須要在保存的時候先保存班級,在保存學生,不然出錯: object references an unsaved transient instance - save the transient instance before flushing:
ClassRoom classRoom = new ClassRoom(); classRoom.setCname("CS"); Students students = new Students("111"); students.setClassroom(classRoom); session.save(classRoom); session.save(students); tx.commit();
小結:使用<many-to-one>元素進行多對一關聯關係配置,name屬性 指定類的屬性名,column屬性 指定庫表字段名,class屬性 指定類屬性類型(加上姓,即包名),not-null屬性 指定屬性是否容許爲空,cascade屬性 指定是否級聯保存和更新:save-update、delete、all、none。
一對多單向外鍵關聯
當類與類創建了關聯,程序能很方便的從一個對象導航到另外一個或一組與之關聯的對象,有了student對象,就能夠經過student對象獲得這個學生所屬的班級的信息——students.getClassroom();,對於班級對象,若是想要獲得某個學生的信息,怎麼辦呢?這時候能夠反過來控制,一方控制多方,下面進行一對多單向外鍵關聯。
簡單說就是和以前多對一相反,以前是多方持有一方的引用,而一對多關聯關係是一方持有多方的集合的引用,注意區別:這裏是持有多方的集合。
基於註解的配置:
@OneToMany(cascade={CascadeType.ALL},fetch=FetchType.LAZY),@JoinColumn(name=""),除了級聯以外,還要設置一方爲懶加載模式。且外鍵仍是加在了多方學生表裏,只不過控制權變了,以前多對一關聯是多方學生持有班級外鍵,控制班級,如今一對多關聯,表裏仍是多方學生持有班級一方的外鍵,只不過控制權交給了班級,讓班級控制學生。不要混淆。
import javax.persistence.*; import java.util.Set; //班級類是一方,一方持有多方的引用 @Entity public class ClassRoom { private int cid;//班級編號 private String cname;//班級名稱 private Set<Students> stus ;//班級的學生集合是多方 // 如今是一方維護多方了,主控權交給了一方,設置級聯,一方要設置懶加載,推薦! @OneToMany(cascade={CascadeType.ALL},fetch=FetchType.LAZY) @JoinColumn(name="cid") // 設置一方的外鍵,這裏是cid,由於實際上這個外鍵仍是加在多方,只不過控制權變了。 public Set<Students> getStus() { return stus; } public void setStus(Set<Students> stus) { this.stus = stus; } @Id @GeneratedValue public int getCid() { return cid; } public void setCid(int cid) { this.cid = cid; } public String getCname() { return cname; } public void setCname(String cname) { this.cname = cname; } }
注意,不論多對一仍是一對多,多方都要顯式保留無參構造器。
import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; //學生實體類 @Entity public class Students { private int sid; //編號 private String sname; //姓名 //注意:必定要保留這個默認不帶參數的構造方法 public Students(){ } public Students(String sname) { this.sname = sname; } @Id @GeneratedValue public int getSid() { return sid; } public void setSid(int sid) { this.sid = sid; } public String getSname() { return sname; } public void setSname(String sname) { this.sname = sname; } }
執行數據庫腳本,發現一方(主控方)仍是和以前多對一的表結構同樣,多方也是如此。
create table ClassRoom (cid integer not null auto_increment, cname varchar(255), primary key (cid))
create table Students (sid integer not null auto_increment, sname varchar(255), cid integer, primary key (sid))
執行測試,保存學生,由於如今關係是一方維護,控制多方。確定保存主控方——班級(和以前相反,以前多對一保存的是多方學生對象),可是本質上仍是先保存的學生班級,再自動保存學生,這點和多對一本質同樣。
Set<Students> stus = new HashSet<>(); stus.add(new Students("zhangsan")); stus.add(new Students("lisi")); stus.add(new Students("wangwu")); stus.add(new Students("zhaoliu")); stus.add(new Students("sunqi")); ClassRoom c = new ClassRoom(); c.setCname("cs001"); c.setStus(stus); session.save(c); tx.commit();
生成的腳本以下:先插入外鍵的班級對象,在執行五個學生的插入操做,最後執行五個更新,爲sid=1。。。5的學生,更新cid爲2
Hibernate: insert into ClassRoom (cname) values (?) Hibernate: insert into Students (sname) values (?) Hibernate: insert into Students (sname) values (?) Hibernate: insert into Students (sname) values (?) Hibernate: insert into Students (sname) values (?) Hibernate: insert into Students (sname) values (?) Hibernate: update Students set cid=? where sid=? Hibernate: update Students set cid=? where sid=? Hibernate: update Students set cid=? where sid=? Hibernate: update Students set cid=? where sid=? Hibernate: update Students set cid=? where sid=?
總結:多對一時候,多方設置EAGER,一方設置LAZY,也就是說,若是是多對一,多方控制一方,那麼多方設置積極加載,一方無需多餘配置,反過來,若是是一對多關係,一方控制多方,那麼一方設置懶加載,多方無需多餘配置,可是不論哪一種,多方都顯式加上一個不帶參數的構造器。
一對多裏的懶加載
記得以前總結,get和load的查詢方式源碼的時候,就總結了一下懶加載load裏的應用,以前說Hibernate中,當訪問的數據量過大時,用緩存也不太合適, 由於內存容量有限 ,爲了減小併發量,減小系統資源的消耗,Hibernate用懶加載機制來彌補這種缺陷,可是這只是彌補而不是用了懶加載整體性能就提升了。懶加載也被稱爲延遲加載,它在查詢的時候不會馬上訪問數據庫,而是返回代理對象,好比以前總結的load方式查詢,當真正去使用對象的時候纔會訪問數據庫。除了load查詢默認使用懶加載,如今咱們的一對多關聯映射也使用了lazy加載,下面進行實際驗證測試:
public void testQuery() { Session session = sessionFactory.getCurrentSession(); Transaction tx = session.beginTransaction(); try { // 首先查詢班級,cid=1的班級 ClassRoom c =(ClassRoom) session.get(ClassRoom.class, 1); // 經過班級導航到學生,遍歷學生獲得名字 for(Students s : c.getStus()) { System.out.println("姓名 :" + s.getSname()); } tx.commit(); } catch(Exception ex) { ex.printStackTrace(); tx.rollback(); } }
執行以後,debug發現:在沒有使用班級對象的時候,只有這樣一條SQL語句:從classroom表查詢,cid=1的班級,使用使用AS賦給列一個別名。
Hibernate: select classroom0_.cid as cid0_0_, classroom0_.cname as cname0_0_ from ClassRoom classroom0_ where classroom0_.cid=?
等執行到for了,纔打印這一語句:
Hibernate: select stus0_.cid as cid0_1_, stus0_.sid as sid1_, stus0_.sid as sid1_0_, stus0_.sname as sname1_0_ from Students stus0_ where stus0_.cid=?
充分說明這是執行的懶加載模式。一方控制多方,一方設置懶加載,若是什麼都不設置,會是什麼狀況?通過驗證,發現和顯式設置懶加載效果同樣,也就是說,one-to-many(元素)的懶加載是默認的,這是必須的,是經常使用的策略。一對多的時候,查詢主對象時默認是懶加載。即:查詢主對象的時候不會把從對象查詢出來,使用從對象的時候才加載從對象。
若是人爲設置爲積極加載,則直接所有查詢,@OneToMany(cascade={CascadeType.ALL},fetch=FetchType.EAGER),SQL語句爲以下,進行了外鏈接的查詢。一次性查了主對象和從對象出來。
Hibernate: select classroom0_.cid as cid0_1_, classroom0_.cname as cname0_1_, stus1_.cid as cid0_3_, stus1_.sid as sid3_, stus1_.sid as sid1_0_, stus1_.sname as sname1_0_ from ClassRoom classroom0_ left outer join Students stus1_ on classroom0_.cid=stus1_.cid where classroom0_.cid=?
基於xml文件配置:
一方做爲主控方:
<set name="" >
<key column=""/>
<one-to-many class= "" />
</set>
一方是班級,持有多方的集合,以下配置:
<hibernate-mapping> <class name="net.nw.vo.fk.otm.ClassRoom" table="classroom"> <id name="cid" column="cid" type="int"> <generator class="native"/> </id> <property name="cname" column="cname" type="string"/> <set name="stus" > <!-- 外鍵仍是班級cid --> <key column="cid"/> <one-to-many class="net.nw.vo.fk.otm.Students" /> </set> </class> </hibernate-mapping>
多方是學生,做爲從對象,別忘了,保留無參構造器,以下配置:
<hibernate-mapping> <class name="net.nw.vo.fk.otm.Students" table="students"> <id name="sid" column="sid" type="int"> <generator class="native"/> </id> <property name="sname" column="sname" type="string"/> </class> </hibernate-mapping>
一對多雙向外鍵關聯
其實相似以前的一對一雙向外鍵關聯,也是互相持有對方的引用,故也叫雙向一對多自身關聯。多方持有一方的引用,@ManyToOne(cascade={CascadeType.ALL}),@JoinColumn(name="")。反過來,一方也持有多方的集合,@OneToMany(cascade={CascadeType.ALL}),@JoinColumn(name="")。代碼以下:
基於註解的配置:
import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; //學生實體類,屬於多方,持有一方的引用 @Entity public class Students { private int sid; //編號 private String sname; //姓名 private ClassRoom classroom;//學生班級屬於一方 //注意:必定要在多方保留這個默認不帶參數的構造方法 public Students() { } public Students(String sname) { this.sname = sname; } // 多方是設置積極加載,所有級聯 @ManyToOne (cascade={CascadeType.ALL}, fetch=FetchType.EAGER) @JoinColumn(name="cid",referencedColumnName="cid") // 外鍵設置爲班級id,cid public ClassRoom getClassroom() { return classroom; } public void setClassroom(ClassRoom classroom) { this.classroom = classroom; } @Id @GeneratedValue public int getSid() { return sid; } public void setSid(int sid) { this.sid = sid; } public String getSname() { return sname; } public void setSname(String sname) { this.sname = sname; } }
關鍵是一方,也必須持有多方的集合,造成你中有我,我中有你的局面,互相控制。可是仍是注意,本質上,數據庫表裏外鍵cid仍是加在了學生表——多方的表裏。
import javax.persistence.*; import java.util.Set; //班級類 @Entity public class ClassRoom { private int cid;//班級編號 private String cname;//班級名稱 private Set<Students> stus; // 一方也持有了多方:學生的集合引用 // 一方也要控制多方,一方設置懶加載,外鍵仍是cid,也就是外鍵仍是加在多方——學生表。 @OneToMany(cascade={CascadeType.ALL},fetch=FetchType.LAZY) @JoinColumn(name="cid") public Set<Students> getStus() { return stus; } public void setStus(Set<Students> stus) { this.stus = stus; } @Id @GeneratedValue public int getCid() { return cid; } public void setCid(int cid) { this.cid = cid; } public String getCname() { return cname; } public void setCname(String cname) { this.cname = cname; } }
測試腳本生成。和以前表同樣,只不過控制權雙方都有了:
alter table Students drop foreign key FK73AC29B8559B6D03 drop table if exists ClassRoom drop table if exists Students create table ClassRoom (cid integer not null auto_increment, cname varchar(255), primary key (cid)) create table Students (sid integer not null auto_increment, sname varchar(255), cid integer, primary key (sid)) alter table Students add index FK73AC29B8559B6D03 (cid), add constraint FK73AC29B8559B6D03 foreign key (cid) references ClassRoom (cid)
此時先保存誰均可以!控制權是雙方都有。
基於xml配置:
<set name="" >
<key column=""></key>
<one-to-many class=""/>
</set>
本例代碼以下:
<hibernate-mapping> <class name="net.nw.vo.bfk.mto.Students" table="students"> <id name="sid" column="sid" type="int"> <generator class="native"/> </id> <property name="sname" column="sname" type="string"/> <many-to-one name="classroom" column="cid"/> </class> </hibernate-mapping> ---------------------------------------------------------------------------------- <hibernate-mapping> <class name="net.nw.vo.bfk.mto.ClassRoom" table="classroom"> <id name="cid" column="cid" type="int"> <generator class="native"/> </id> <property name="cname" column="cname" type="string"/> <set name="stus" > <key column="cid"/> <one-to-many class="net.nw.vo.bfk.mto.Students" /> </set> </class> </hibernate-mapping>
小結:在關係模型中,只存在外鍵參照關係,並且是many方參照one方。
多對多的關聯關係映射
如今有一個角色類,和一個特權類,前者保存了都有哪些人(角色)擁有哪些特權,後者保存的是一些特權,好比能夠作什麼,不能夠作什麼等讓哪些人擁有。如圖類關係:
這就是一個多對多的例子,他們之間在數據庫如何實現的關聯呢?顯然不能互相持有對方主鍵作外鍵,那麼就須要用到一個新的表——映射表做爲中間表:
再舉一個最熟悉的學生的例子,現實中,學生和教師就構成了多對多的關聯關係。一個教師能夠教不少學生,同時一個學生能夠師從不少老師,拿這個例子說明。
多對多單向外鍵關聯
import javax.persistence.*; import java.util.Set; //學生實體類 @Entity public class Students { private int sid; //編號 private String sname; //姓名 private Set<Teachers> teachers ; // 我設置學生這個多方去持有老師這個多方的集合,去控制老師 //注意:必定要保留這個默認不帶參數的構造方法 public Students() { } public Students(String sname) { this.sname = sname; } // 先設置多對多的關聯,以後必須生成一箇中間表,使用JoinTable註解 @ManyToMany(cascade=CascadeType.ALL) @JoinTable( // 設置中間表名 name="teachers_students", // 指定當前對象的外鍵,本表在中間表的外鍵名稱 joinColumns={@JoinColumn(name="sid")}, // 指定關聯對象的外鍵,另外一個表在中間表的外鍵名稱。 inverseJoinColumns={@JoinColumn(name="tid")} ) public Set<Teachers> getTeachers() { return teachers; } public void setTeachers(Set<Teachers> teachers) { this.teachers = teachers; } @Id @GeneratedValue public int getSid() { return sid; } public void setSid(int sid) { this.sid = sid; } public String getSname() { return sname; } public void setSname(String sname) { this.sname = sname; } }
另外一個多方,老師不作多餘配置:
import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; @Entity public class Teachers { private int tid;//教師的編號 private String tname;//教師姓名 public Teachers() { } public Teachers(String tname) { this.tname = tname; } @Id @GeneratedValue public int getTid() { return tid; } public void setTid(int tid) { this.tid = tid; } public String getTname() { return tname; } public void setTname(String tname) { this.tname = tname; } }
生成的數據庫腳本以下:
create table Students (sid integer not null auto_increment, sname varchar(255), primary key (sid))
create table Teachers (tid integer not null auto_increment, tname varchar(255), primary key (tid))
create table teachers_students (sid integer not null, tid integer not null, primary key (sid, tid))
主要關注中間表,sid和tid都是做爲了中間表的聯合主鍵,他們同時也是外鍵:
// 由於學生持有教師的集合,先設置教師 Set<Teachers> teachers = new HashSet<>(); teachers.add(new Teachers("Wang")); teachers.add(new Teachers("Li")); teachers.add(new Teachers("Song")); teachers.add(new Teachers("Zhang")); Students s = new Students(); s.setSname("zhangsan"); s.setTeachers(teachers); session.save(s); tx.commit();
基於xml的多對多單向外鍵關係配置:
學生這個多方持有老師的集合,那麼持有對方集合的學生映射文件配置以下:
<hibernate-mapping> <class name="net.nw.vo.fk.mtm.Students" table="students"> <id name="sid" column="sid" type="int"> <generator class="native"/> </id> <property name="sname" column="sname" type="string"/> <!-- 學生表持有老師的集合,以下進行配置 --> <set name="teachers" table="students_teachers" cascade="all"> <!-- table設置中間表,級聯是all --> <!-- key設置本對象在中間表的外鍵sid --> <key column="sid"/> <!-- many-to-many 標籤設置對方的表(老師)在中間表的外鍵tid --> <many-to-many class= "net.nw.vo.fk.mtm.Teachers" column="tid"/> </set> </class> </hibernate-mapping>
老師表配置就簡單了:
<hibernate-mapping> <class name="net.nw.vo.fk.mtm.Teachers" table="teachers"> <id name="tid" column="tid" type="int"> <generator class="native"/> </id> <property name="tname" column="tname" type="string"/> </class> </hibernate-mapping>
進行測試(刪除以前的表,先刪除中間表,在刪除老師表,最後刪除學生表):
Set<Teachers> teachers = new HashSet<>(); teachers.add(new Teachers("Teacher Wang")); teachers.add(new Teachers("Teacher Li")); teachers.add(new Teachers("Teacher Song")); teachers.add(new Teachers("Teacher Zhang")); Students s = new Students(); s.setSname("zhangsan"); s.setTeachers(teachers); session.save(s); tx.commit();
多對多雙向外鍵關聯
和以前的相似,是互相持有對方的集合,雙方持有對方的集合對象,其中一方設置@ManyToMany(mappedBy=""),另外一方:
@ManyToMany @JoinTable( name="", joinColumns={@JoinColumn(name="")}, inverseJoinColumns={@JoinColumn(name="")} )
基於註解的配置,看具體代碼:
import javax.persistence.*; import java.util.Set; //學生實體類 @Entity public class Students { private int sid; //編號 private String sname; //姓名 private Set<Teachers> teachers ; //注意:必定要保留這個默認不帶參數的構造方法 public Students() { } public Students(String sname) { this.sname = sname; } @ManyToMany(cascade=CascadeType.ALL) @JoinTable( name="teachers_students", joinColumns={@JoinColumn(name="sid")}, inverseJoinColumns={@JoinColumn(name="tid")} ) public Set<Teachers> getTeachers() { return teachers; } public void setTeachers(Set<Teachers> teachers) { this.teachers = teachers; } @Id @GeneratedValue public int getSid() { return sid; } public void setSid(int sid) { this.sid = sid; } public String getSname() { return sname; } public void setSname(String sname) { this.sname = sname; } }
關鍵是另外一方的配置,前面總結了,雙向關聯不會真的是互相維持,只能交給一方去維護:
import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.ManyToMany; import java.util.Set; @Entity public class Teachers { private int tid;//教師的編號 private String tname;//教師姓名 private Set<Students> stus ; public Teachers() { } public Teachers(String tname) { this.tname = tname; } // 把控制權交給student類——teachers集合引用 @ManyToMany(mappedBy="teachers") public Set<Students> getStus() { return stus; } public void setStus(Set<Students> stus) { this.stus = stus; } @Id @GeneratedValue public int getTid() { return tid; } public void setTid(int tid) { this.tid = tid; } public String getTname() { return tname; } public void setTname(String tname) { this.tname = tname; } }
生成數據庫腳本:(和以前的單向多對多同樣的表結構,關鍵看實體中控制權的變化)
create table Students (sid integer not null auto_increment, sname varchar(255), primary key (sid))
create table Teachers (tid integer not null auto_increment, tname varchar(255), primary key (tid))
create table teachers_students (sid integer not null, tid integer not null, primary key (sid, tid))
基於xml的配置:
<set name="teachers" table="students_teachers">
<key column="sid"></key>
<many-to-many class="net.nw.vo.Teachers" column="tid"/>
</set>
另外一方:
<set name="students" table="students_teachers">
<key column="tid"></key>
<many-to-many class="net.nw.vo.Students" column="sid"/>
</set>
具體代碼:
<hibernate-mapping> <class name="net.nw.vo.bfk.mtm.Students" table="students"> <id name="sid" column="sid" type="int"> <generator class="native"/> </id> <property name="sname" column="sname" type="string"/> <set name="teachers" table="students_teachers" cascade="all"> <key column="sid"/> <many-to-many class= "net.nw.vo.bfk.mtm.Teachers" column="tid"/> </set> </class> </hibernate-mapping> --------------------------------------------------------------------- <hibernate-mapping> <class name="net.nw.vo.bfk.mtm.Teachers" table="teachers"> <id name="tid" column="tid" type="int"> <generator class="native"/> </id> <property name="tname" column="tname" type="string"/> <set name="stus" table="students_teachers" cascade="all"> <key column="tid"/> <many-to-many class= "net.nw.vo.bfk.mtm.Students" column="sid"/> </set> </class> </hibernate-mapping>
注意:set元素配置;
屬性name 指定類的屬性名,table指定多對多關聯關係中間表,cascade 級聯操做屬性:save-update、delete、all、none,通常all就ok,lazy屬性能夠指定是不是懶加載。set的子元素key元素——設定本表在中間表的外鍵名稱。
inverse屬性設置:
關聯關係的優缺點
問題小結