關聯映射就是將關聯關係映射到資料庫里,在對象模型中就是一個或多個引用。 一:配置單向多對一關聯 在Emp類中定義一個Dept屬性,而在Dept類中無須定義用於存放Emp對象的集合屬性 01.Dept.java 02.Emp.java 03.Dept.hbm.xml 04.Emp.hbm.xml 05 ...
關聯映射就是將關聯關係映射到資料庫里,在對象模型中就是一個或多個引用。
一:配置單向多對一關聯
在Emp類中定義一個Dept屬性,而在Dept類中無須定義用於存放Emp對象的集合屬性
01.Dept.java
package cn.zhang.entity; //部門實體類 public class Dept { private Integer deptid;//編號 private String deptname;//名稱 public Integer getDeptid() { return deptid; } public void setDeptid(Integer deptid) { this.deptid = deptid; } public String getDeptname() { return deptname; } public void setDeptname(String deptname) { this.deptname = deptname; } }
02.Emp.java
package cn.zhang.entity; //員工實體類 public class Emp { private Integer empno;//編號 private String empname;//姓名 private Dept dept;//所屬部門 public Dept getDept() { return dept; } public void setDept(Dept dept) { this.dept = dept; } public Integer getEmpno() { return empno; } public void setEmpno(Integer empno) { this.empno = empno; } public String getEmpname() { return empname; } public void setEmpname(String empname) { this.empname = empname; } }
03.Dept.hbm.xml
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="cn.zhang.entity"> <class name="Dept" table="DEPT"> <!--主鍵生成策略--> <id name="deptid" column="DEPTID"> <generator class="sequence"> <param name="sequence">SQ_Num</param> </generator> </id> <property name="deptname" type="string" column="deptname"/> </class> </hibernate-mapping>
04.Emp.hbm.xml
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="cn.zhang.entity"> <class name="Emp" table="EMP"> <!-- 主鍵生成策略 --> <id name="empno" column="empno"> <generator class="sequence"> <param name="sequence">SQ_Num</param> </generator> </id> <property name="empname" type="string" column="empname"/> <!-- 多對一(員工對部門) --> <many-to-one name="dept" column="deptid" class="Dept"></many-to-one> </class> </hibernate-mapping>
05.hibernate.cfg.xml 配置文件
<?xml version='1.0' encoding='utf-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <!-- Database connection settings --> <property name="connection.driver_class">oracle.jdbc.OracleDriver</property> <property name="connection.url">jdbc:oracle:thin:@localhost:1521:orcl</property> <property name="connection.username">zhangzong</property> <property name="connection.password">123</property> <!-- SQL dialect (SQL 方言)--> <property name="dialect">org.hibernate.dialect.Oracle10gDialect</property> <!-- Drop and re-create the database schema on startup --> <property name="hbm2ddl.auto">create</property> <!-- Echo all executed SQL to stdout 在控制台列印後臺的SQL語句--> <property name="show_sql">true</property> <!-- 格式化顯示SQL --> <property name="format_sql">true</property> <!-- JDBC connection pool (use the built-in) --> <!-- <property name="connection.pool_size">1</property> --> <!-- Enable Hibernate's automatic session context management 指定當前session範圍和上下文--> <!-- <property name="current_session_context_class">thread</property> --> <!-- Disable the second-level cache --> <!-- <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>--> <mapping resource="cn/zhang/entity/Dept.hbm.xml" /> <mapping resource="cn/zhang/entity/Emp.hbm.xml" /> </session-factory> </hibernate-configuration>
06.用於獲得session對象和關閉session對象的工具類HibernateUtil
package cn.zhang.util; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; public class HibernateUtil { //初始化一個ThreadLocal對象,有get和set方法 private static final ThreadLocal<Session> sessionTL=new ThreadLocal<Session>(); private static Configuration configuration; private final static SessionFactory sessionFactory; static{ configuration=new Configuration().configure(); sessionFactory=configuration.buildSessionFactory(); } //獲得session對象 public static Session currentSession() { //sessionTL的get方法根據當前線程返回其對應的線程內部變數,即Session對象,多線程情況下共用資料庫連接是不安全的。 //ThreadLocal保證了每個線程都有自己的session對象 Session session=(Session)sessionTL.get(); if (session==null) { session=sessionFactory.openSession(); sessionTL.set(session); } return session; } //關閉session對象 public static void closeSession() { Session session=(Session)sessionTL.get(); sessionTL.set(null); session.close(); } }
07.測試類
@Test //多對一的單向關聯關係 public void TestOne(){ Session session = HibernateUtil.currentSession(); Transaction tx = session.beginTransaction(); Dept dept=new Dept(); dept.setDeptname("開發部"); Emp emp=new Emp(); emp.setDept(dept); emp.setEmpname("張總"); session.save(dept); session.save(emp); tx.commit(); HibernateUtil.closeSession(); }
二:配置雙向的一對多關聯
在上一個例子中,已經建立Emp類到Dept類的多對一關聯,下麵再增加Dept到Emp類的一對多關聯,
在Dept類中增加一個集合類型的emps屬性:
private Set<Emp> emps=new HashSet<Emp>();//員工集合 public Set<Emp> getEmps() { return emps; } public void setEmps(Set<Emp> emps) { this.emps = emps; }
在Dept.hbm.xml中也會改變為:
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="cn.zhang.entity"> <class name="Dept" table="DEPT"> <id name="deptid" column="DEPTID"> <generator class="sequence"> <param name="sequence">SQ_Num</param> </generator> </id> <property name="deptname" type="string" column="deptname"/> <!-- 映射集合類型的emps屬性 --> <!-- name屬性:設定持久化類的屬性名。此處為Dept類的emps --> <set name="emps" cascade="save-update" inverse="true"> <!-- column屬性設定與所關聯的持久化類對應的表的外鍵,此處為EMP表的deptid欄位 --> <key column="deptid"></key> <!-- class屬性設定與所關聯的持久化類,此處為Emp類 --> <one-to-many class="Emp"></one-to-many> </set> </class> </hibernate-mapping>
補充:cascade屬性和inverse屬性(會新寫一篇博客)
01."cascade"屬性
"cascade"-直譯過來就是"級聯、串聯"的意思,書面化的解釋為"該屬性會使我們在操作主對象時,同時Hibernate幫助我們完成從屬對象 相應的操作(比如,有Customer和Order這兩張表,關係為一對多,只使用JDBC刪除Customer表中的一行記錄時,我們還需要手動的將 Order表中與之關聯的記錄全都刪除,使用Hibernate的'cascade'屬性後,當我們刪除一條Customer記錄時,Hibernate 會幫助我們完成相應Order表記錄的刪除工作,方便了我們的工作)"。
02."inverse"屬性
"inverse" -直譯過來就是"反轉,使顛倒"的意思,書面化的解釋為"是否將關係維護的權力交給對方"(這個解釋真夠蛋疼的-_-!!,就是理解不了)。 Hibernate中的"inverse"屬性只有兩個值"true"和"false"。"true"表示將關係維護的權力交給對方,"false"表示不交出維護權力(預設值)。
推薦博客:http://www.cnblogs.com/o-andy-o/archive/2012/03/26/2418235.html
測試:
@Test public void TestThree(){ //獲得session對象 Session session = HibernateUtil.currentSession(); //開啟事務 Transaction tx = session.beginTransaction(); //建立一個Dept對象和Emp對象 Dept dept=new Dept(); dept.setDeptname("就業部"); Emp emp=new Emp(); emp.setEmpname("坤坤"); //建立Dept和Emp對象的一對多雙向關聯關係 emp.setDept(dept); dept.getEmps().add(emp); //保存Dept對象 session.save(dept); //提交事務 tx.commit(); //關閉session連接 HibernateUtil.closeSession(); }
三:配置單向多對多關聯 --利用第三張表建立兩張表之間的聯繫
建立從Project(項目)類到Emp(員工)類的單向多對多關聯。
需在Project定義集合類型emps屬性,Emp類中不需要定義集合類型的projects屬性。
Project.java
package cn.zhang.entity; import java.util.HashSet; import java.util.Set; public class Project { private Integer proid; private String proname; private Set<Emp> emps = new HashSet<Emp>(); public Integer getProid() { return proid; } public void setProid(Integer proid) { this.proid = proid; } public String getProname() { return proname; } public void setProname(String proname) { this.proname = proname; } public Set<Emp> getEmps() { return emps; } public void setEmps(Set<Emp> emps) { this.emps = emps; } }
Project.hbm.xml --利用第三張表建立兩張表之間的聯繫
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="cn.zhang.entity"> <class name="Project" table="PROJECT"> <id name="proid" type="java.lang.Integer"> <generator class="sequence"> <param name="sequence">SQ_Num</param> </generator> </id> <property name="proname" type="java.lang.String" column="PRONAME"/> <!-- 多對多關聯 --> <set name="emps" table="PROEMP" cascade="save-update" > <key column="proid" /> <many-to-many class="Emp" column="empno" /> </set> </class> </hibernate-mapping>
測試:
@Test public void TestOne(){ Session session = HibernateUtil.currentSession(); Transaction tx = session.beginTransaction(); //創建EMP對象 Emp emp=new Emp(); emp.setEmpname("李小龍"); //創建Pro對象 Project pro=new Project(); pro.setProname("海澱花園"); //指定工程需要的員工 pro.getEmps().add(emp); session.save(pro); // 事務提交 tx.commit(); HibernateUtil.closeSession(); }
三:配置雙向多對多關聯 --利用第三張表建立兩張表之間的聯繫
對於雙向多對多關聯,需要把一端的inverse屬性設為true,關聯的兩端都可以使用<set>元素。
Project類--定義集合類型的emps屬性
Emp類--定義集合類型的projects屬性
Project.java:
package cn.zhang.entity; import java.util.HashSet; import java.util.Set; public class Project { private Integer proid; private String proname; private Set<Emp> emps = new HashSet<Emp>(); public Integer getProid() { return proid; } public void setProid(Integer proid) { this.proid = proid; } public String getProname() { return proname; } public void setProname(String proname) { this.proname = proname; } public Set<Emp> getEmps() { return emps; } public void setEmps(Set<Emp> emps) { this.emps = emps; } }
Emp.java:
package cn.zhang.entity; import java.util.HashSet; import java.util.Set; //員工實體類 public class Emp { private Integer empno; private String empname; private Set<Project> projects = new HashSet<Project>(); public Set<Project> getProjects() { return projects; } public void setProjects(Set<Project> projects) { this.projects = projects; } public Integer getEmpno() { return empno; } public void setEmpno(Integer empno) { this.empno = empno; } public String getEmpname() { return empname; } public void setEmpname(String empname) { this.empname = empname; } }
Project.hbm.xml
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="cn.zhang.entity"> <class name="Project" table="PROJECT"> <id name="proid" type="java.lang.Integer"> <generator class="sequence"> <param name="sequence">SQ_Num</param> </generator> </id> <property name="proname" type="java.lang.String" column="PRONAME"/> <!-- 多對多關聯 --> <set name="emps" table="PROEMP" cascade="save-update" > <key column="proid" /> <many-to-many class="Emp" column="empno" /> </set> </class> </hibernate-mapping>
Emp.hbm.xml
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="cn.zhang.entity"> <class name="Emp" table="EMP"> <id name="empno" column="empno"> <generator class="sequence"> <param name="sequence">SQ_Num</param> </generator> </id> <property name="empname" type="string" column="empname" /> <!--多對多關聯 --> <set name="projects" table="PROEMP" cascade="save-update" inverse="true"> <key column="empno" /> <many-to-many class="Project" column="proid" /> </set> </class> </hibernate-mapping>
測試:
@Test public void TestOne(){ Session session = HibernateUtil.currentSession(); Transaction tx = session.beginTransaction(); //創建EMP對象 Emp emp=new Emp(); emp.setEmpname("李小龍"); Emp emp2=new Emp(); emp2.setEmpname("小龍"); Emp emp3=new Emp(); emp3.setEmpname("李龍"); //創建Pro對象 Project pro=new Project(); pro.setProname("海澱花園"); Project pro2=new Project(); pro2.setProname("海澱花園fd"); //指定工程需要的員工 pro.getEmps().add(emp); pro.getEmps().add(emp2); pro.getEmps().add(emp3); pro2.getEmps().add(emp3); pro2.getEmps().add(emp2); //指定員工所屬的工程 //emp.getProjects().add(pro); session.save(pro); session.save(pro2); // 事務提交 tx.commit(); HibernateUtil.closeSession(); }
註意:雙向多對多,還可以拆成兩個多對一
四:建立多對多雙向關聯 拆成兩個一對多 --利用第三張表建立兩張表之間的聯繫
主要思想:新建立一個關係實體類和兩張表關聯的映射文件,主要在此映射文件中配置關聯關係,其他兩個映射文件只要配置基礎映射
ProEmp.java
package cn.zhang.entity; //關聯實體類 public class ProEmp { private Integer id; private Project pro; //項目集合 private Emp emp; //部門集合 public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Project getPro() { return pro; } public void setPro(Project pro) { this.pro = pro; } public Emp getEmp() { return emp; } public void setEmp(Emp emp) { this.emp = emp; } }
Emp.java
package cn.zhang.entity; import java.util.HashSet; import java.util.Set; //員工實體類 public class Emp { private Integer empno; private String empname; private Set<ProEmp> projects = new HashSet<ProEmp>();//與ProEmp關聯 public Set<ProEmp> getProjects() { return projects; } public void setProjects(Set<ProEmp> projects) { this.projects = projects; } public Integer getEmpno() { return empno; } public void setEmpno(Integer empno) { this.empno = empno; } public String getEmpname() { return empname; } public void setEmpname(String empname) { this.empname = empname; } }
Project.java
package cn.zhang.entity; import java.util.HashSet; import java.util.Set; //員工實體類 public class Emp { private Integer empno; private String empname; private Set<ProEmp> projects = new HashSet<ProEmp>();//與ProEmp關聯 public Set<ProEmp> getProjects() { return projects; } public void setProjects(Set<ProEmp> projects) { this.projects = projects; } public Integer getEmpno() { return empno; } public void setEmpno(Integer empno) { this.empno = empno; } public String getEmpname() { return empname; } public void setEmpname(String empname) { this.empname = empname; } }
Emp.hbm.xml
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="cn.zhang.entity"> <class name="Emp" table="EMP"> <id name="empno" column="empno"> <generator class="sequence"> <param name="sequence">SQ_Num</param> </generator>