Hibernate中inverse属性-详细介绍

来源:互联网 发布:关于网络鬼片 编辑:程序博客网 时间:2024/06/05 10:37

这几天,复习Hibernate,没想到还感受了一把“温故而知新”的乐趣,废话少说,“实践才是检验真理的唯一标准” 直接上代码:


package com.hibernate.entity;import java.util.HashSet;import java.util.Set;/** * 部门实体类 * @author dabing * */public class Department {private int id;private String name;private Set<Employee> employees=new HashSet<Employee>();public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Set<Employee> getEmployees() {return employees;}public void setEmployees(Set<Employee> employees) {this.employees = employees;}}

package com.hibernate.entity;/** * 员工实体类 * @author dabing * */public class Employee {private int id;private String name;private Department department;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Department getDepartment() {return department;}public void setDepartment(Department department) {this.department = department;}}


Department.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><class name="com.hibernate.entity.Department"><id name="id"><generator class="sequence"><param name="sequence">department_id_seq</param></generator></id><property name="name"></property><set name="employees" table="Employee" inverse="false"><key column="d_id"></key><one-to-many class="com.hibernate.entity.Employee"/></set></class></hibernate-mapping>

Employee.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>    <class name="com.hibernate.entity.Employee">        <id name="id">            <generator class="sequence">                <param name="sequence">employee_id_seq</param>            </generator>        </id>        <property name="name"></property>                <many-to-one name="department" column="d_id" class="com.hibernate.entity.Department"></many-to-one>            </class></hibernate-mapping>

Hibernate辅助类:

package com.hibernate.util;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.hibernate.cfg.Configuration;public class HibernateUtil {private static Configuration configuration;private static SessionFactory sessionFactory;private static final ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();static {configuration = new Configuration();configuration.configure();sessionFactory = configuration.buildSessionFactory();}public static Session getSession() {Session session = (Session) threadLocal.get();if (session == null || !session.isOpen()) {session = sessionFactory.openSession();threadLocal.set(session);}return session;}}

package com.entity;import org.hibernate.Session;import org.junit.Test;import com.hibernate.entity.Department;import com.hibernate.entity.Employee;import com.hibernate.util.HibernateUtil;public class TestInverse {public Session session=HibernateUtil.getSession();/** *  * 注意: *  * 一:代码1、代码2中: *  *   emp1.setDepartment(department)与emp2.setDepartment(department),说明了该员工属于那个部门,也就是在Employee与Department对象上建立起了关联 , *  *   在数据库中,hibernate需要将对象上建立起的关联映射到数据库中, *  *   也就是Employee(员工表)的外键更新为Department(部门表)的id主键,这样就在数据库中建立起了关联; *  *   (这也就是为什么会出现两条"update Employee set name=?, d_id=? where id=?"语句的原因) *    *   注意: *        *       1.如果在程序中先保存Employee(员工),然后在保存Department(部门),这时就相当于一个部门还有没有建立起来,就已经开始招员工了,等到部门建立起来 *         在将招收的员工  放到 该部门下(也就是update更新员工的外键列 ),所以这时会有两条update语句出现; *        *       2.如果在程序中先保存Department(部门),然后在保存Employee(员工),因为这时Employee(员工)已经知道了所对应的Department(部门), *         所以这时就不会有这两条update语句出现了; *        *        *  *  * 二:代码3、代码4中: *  *   department.getEmployees().add(emp1)与 department.getEmployees().add(emp2),说明了该部门有哪些员工,也就是在Department与Employee对象上建立起了关联, *  *   在数据库中,hibernate同样也需要将对象上建立起关联映射到数据库中(同样这里也是更新外键), *  *   也就是Employee(员工表)的外键更新为Department(部门表)的id主键,这样就在数据库中建立起了关联; *  *   (这也就是为什么会出现两条"update Employee set d_id=? where id=?"语句的原因) *  *  * 三.在关系型数据库中: *   *    (在双向关联关系中)  *     *    不论是告诉员工(Employee)属于哪个部门(Department),程序中体现为  "emp1.setDepartment(department)" *     *    还是告诉部门(Department)有哪些员工(Employee),在程序中体现为"department.getEmployees().add(emp2);" *     *    还是都指定(也就是即告诉员工(Employee)属于哪个部门(Department),又告诉部门(Department)有哪些员工(Employee))的效果是一样的, *     *    因为都会更新外键列的值, 所以说在关系型数据库中已经足够了, 但是,在对象关联关系中还不够完整.所以有时候 "在双向关联的时候设置双向关联关系"; *  *  * 四:谁在负责维护关联关系?(前提条件:映射文件中one方与many方的inverse属性都设置为false,也就是inverse属性为默认值时) *    *     <1> 代码1、代码2 中:现在的情况是:一旦指名了Employee员工属于哪个Department部门,  *      *        那么Employee员工就会负责维护关联关系,就会通知Hibernate更新数据库(也就是Employee员工需要记住它属于哪个Department部门) *         *         *    <2>代码3、代码4 中:现在 的情况是:一旦指名了Department部门中有哪些Employee员工, *  *        那么Department部门就会负责维护关联关系,就会通知Hibernate更新数据库(也就是Department部门需要记住它有哪些Employee员工) *         *     我们得出结论:现在one方与many方都在负责维护关联关系,于是重复的通知Hibernate更新数据库, 试想效率是多么低下。 *     *     *      * 五. inverse="true"(前提条件:应用与一对多的双向关联映射中): *      *    1.inverse:"是否放弃维护关联关系"; *  *   2.inverse="true" 意思: 表示该对象不负责(放弃)维护关联关系; (注意:Hibernate默认为false) * *   3.当你在部门(Department)中设置inverse="true"时, 这时就算你指名了Department部门中有哪些Employee员工时, *            也就是代码"department.getEmployees().add(emp1)",Hibernate也不会去更新数据库,因为这时部门(Department) *            已经不负责(放弃)维护关联关系 * *     最重要的一点:所谓的关系维护就是指外键列的更新; */@Testpublic void test_inverse(){Department department=new Department();department.setName("人力资源部");Employee emp1=new Employee();emp1.setName("张三");emp1.setDepartment(department);  //代码1  对象模型,建立两个对象的关联 department.getEmployees().add(emp1);    //代码3  对象模型,建立两个对象的关联Employee emp2=new Employee();emp2.setName("李四");emp2.setDepartment(department);  //代码2  对象模型,建立两个对象的关联department.getEmployees().add(emp2);    //代码4  对象模型,建立两个对象的关联session.beginTransaction();/** * 注意: *  *    先保存emp1对象时,在生成的"insert into Employee (name, d_id, id) values (?, ?, ?)"语句中 ,d_id外键列这时肯定是null的; *  * 原因: *  *    因为我们在程序中设置了Employee与Department对象建立起了关联,也就是这句代码"emp1.setDepartment(department);", *  *    因为我们这时是先保存的emp1对象,而department对象这时还没有保存(为null),所以说d_id外键列这时肯定是null的 *  */session.save(department);session.save(emp1);  session.save(emp2);session.getTransaction().commit();}}

对了,大家看了代码大半天,给大家说一个最重要的事情:“所谓的关系维护就是指外键列的更新”!


原创粉丝点击