JPA關係對映之one-to-many和many-to-one(另inverse=“true”解析)
阿新 • • 發佈:2018-12-14
one-to-many(一對多)和many-to-one(多對一)雙向關聯
假設部門與員工是一對多關係,反過來員工與部門就是多對一關係。
Dept.java類
public class Dept implements java.io.Serializable {
private Integer deptId;
private String deptName;
private Set<Emp> emps=new HashSet<Emp>();
}
Emp.java類
public class Emp implements java.io.Serializable { private Integer empNo; private String empName; private Date empBrithday; private Dept dept; }
Dept.hbm.xml
<hibernate-mapping> <class name="com.db.entity.Dept" table="dept" catalog="mydb"> <id name="deptId" type="java.lang.Integer"> <column name="deptId" /> <generator class="native" /> </id> <property name="deptName" type="java.lang.String"> <column name="deptName" length="32" /> </property> <set name="emps" inverse="true" cascade="all"> <key column="deptId" not-null="true" /> <one-to-many class="com.db.entity.Emp" /> </set> </class> </hibernate-mapping>
Emp.hbm.xml
<hibernate-mapping> <class name="com.db.entity.Emp" table="emp" catalog="mydb"> <id name="empNo" type="java.lang.Integer"> <column name="empNo" /> <generator class="native" /> </id> <property name="empName" type="java.lang.String"> <column name="empName" length="20" /> </property> <property name="empBrithday" type="java.util.Date"> <column name="empBrithday"/> </property> <many-to-one name="dept" column="deptId" class="com.db.entity.Dept" not-null="true" fetch="select" cascade="save-update,delete"/> </class> </hibernate-mapping>
hibernate.cfg.xml
<hibernate-configuration>
<session-factory>
<property name="dialect">
org.hibernate.dialect.MySQLDialect
</property>
<property name="connection.url">
jdbc:mysql://localhost:3306/mydb
</property>
<property name="connection.username">root</property>
<property name="connection.password">123456</property>
<property name="connection.driver_class">
com.mysql.jdbc.Driver
</property>
<property name="myeclipse.connection.profile">
MyDBAccount
</property>
<mapping resource="com/db/entity/Dept.hbm.xml" />
<mapping resource="com/db/entity/Emp.hbm.xml" />
</session-factory>
</hibernate-configuration>
測試用例
public class TestOneMany {
public static void main(String[] args) throws ParseException {
// TODO Auto-generated method stub
Session session=HibernateSessionFactory.getSession();
Dept dept1=new Dept();
dept1.setDeptName("開發部");
Emp emp1=new Emp();
emp1.setEmpName("王洋");
String brithString="1999-03-05";
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
Date brithday=sdf.parse(brithString);
emp1.setEmpBrithday(brithday);
Emp emp2=new Emp();
emp2.setEmpName("李林");
brithString="2005-02-07";
brithday=sdf.parse(brithString);
emp2.setEmpBrithday(brithday);
//把emp和dpt分別新增到對方的實力物件中
dept1.getEmps().add(emp1);
dept1.getEmps().add(emp2);
emp1.setDept(dept1);
emp2.setDept(dept1);
session.beginTransaction();
session.save(dept1);
session.getTransaction().commit();
}
}
注意:
在一的set配置中宣告inverse=“true”,意味著Dept不在作為主控方,將關聯關係的維護工作交給關聯物件Emp來完成。
在儲存dept1物件的時不在關心Emp類中dept屬性對應的deptId列,必須由Emp自己去維護,即設定emp.setDept(dept)
上述操作完成的sql語句是:
Hibernate: insert into mydb.dept (deptName) values (?)
Hibernate: insert into mydb.emp (empName, empBrithday, deptId) values (?, ?, ?)
Hibernate: insert into mydb.emp (empName, empBrithday, deptId) values (?, ?, ?)
inverse=“true”解析
在一對多關聯中,在一的一方設定inverse="true",有助於效能的改善。
Inverse是hibernate雙向關係中的基本概念。 inverse的真正作用就是指定由哪一方來維護之間的關聯關係。 當一方中指定了“inverse=false”(預設),那麼那一方就有責任負責之間的關聯關係,說白了就是hibernate如何生成Sql來維護關聯的記錄。 Inverse:負責控制關係,預設為false,也就是關係的兩端都能控制,但這樣會造成一些問題,更新的時候會因為兩端都控制關係,於是重複更新。一般來說有一端要設為true。 Cascade:負責控制關聯物件的級聯操作,包括更新、刪除等,也就是說對一個物件進行更新、刪除時,其它物件也受影響,比如我刪除一個物件,那麼跟它是多對一關係的物件也全部被刪除。 舉例說明區別:
刪除“一”那一端一個物件O的時候,如果“多”的那一端的Inverse設為true,則把“多”的那一端所有與O相關聯的物件外來鍵清空;如果“多”的那一端的Cascade設為Delete,則把“多”的那一端所有與O相關聯的物件全部刪除。
來源於: