Hibernate映射的关系问题

本文章目的是为了测试一对多的关系问题,所以配置信息都是以测试为目的的。
数据库:mysql
实体类:部门实体 Dept,员工实体 Employee
环境准备:

1 hibernate.cfg.xml配置文件
<hibernate-configuration>
    <session-factory>
        <!-- 1. 数据库连接配置 -->
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.url">jdbc:mysql:///jdbc_demo</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.connection.password">root</property>
        <!-- 数据库方法配置     -->
        <property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
        <!-- 2. 其他相关配置 -->
        <property name="hibernate.show_sql">true</property>
        <property name="hibernate.format_sql">true</property>  -->
        <property name="hibernate.hbm2ddl.auto">update</property>
        <!-- 3. 加载所有映射 在测试类中手动的加载配置文件-->
    </session-factory>
</hibernate-configuration>
2 
Dept实体类
public class Dept {
    private int deptId;
    private String deptName;
    // 【一对多】 部门对应的多个员工
    private Set<Employee> emps = new HashSet<Employee>();
    省略setter,getter...;
    省略构造方法;
}
Employee 实体类
public class Employee {
    private int empId;
    private String empName;
    private double salary;
    // 【多对一】员工与部门
    private Dept dept;
    省略setter,getter...;
    省略构造方法;
}
3 映射文件
Dept映射
<hibernate-mapping package="cn.itcast.b_one2Many">  
    <class name="Dept" table="t_dept">
        <id name="deptId">
            <generator class="native"></generator>
        </id>   
        <property name="deptName" length="20"></property>
        <set name="emps" cascade="save-update" inverse="true"> 
             <key column="dept_id"></key>
             <one-to-many class="Employee"/>
         </set>  
    </class>
</hibernate-mapping>
Employee 映射
<hibernate-mapping package="cn.itcast.b_one2Many">  
    <class name="Employee" table="t_employee">
        <id name="empId">
            <generator class="native"></generator>
        </id>   
        <property name="empName" length="20"></property>
        <property name="salary" type="double"></property>       
        <many-to-one name="dept" column="dept_id" class="Dept" cascade="save-update"></many-to-one>      
    </class>
</hibernate-mapping>

上面的配置是一对多双向关联,呆会通过更改配置文件测试 一对多双向关联;多对一单向关联;一对多单向关联;三个的保存操作
测试:
1.一对多双向关联保存

public class App1_save {    
    private static SessionFactory sf;
    static {
        sf = new Configuration()
            .configure()
            .addClass(Dept.class)   
            .addClass(Employee.class)   // 测试使用,可以加载到映射文件,不用在hibernate.cfg.xml引入
            .buildSessionFactory();
    }

    // 保存, 部门方 【一的一方法操作】
    @Test
    public void save() {
        Session session = sf.openSession();
        session.beginTransaction();     
        // 部门对象
        Dept dept = new Dept();
        dept.setDeptName("应用开发部");
        // 员工对象
        Employee emp_zs = new Employee();
        emp_zs.setEmpName("张三2");
        Employee emp_ls = new Employee();
        emp_ls.setEmpName("李四2");
        // 关系
        dept.getEmps().add(emp_zs);
        dept.getEmps().add(emp_ls);

        // 保存       
        session.save(dept); // 保存部门,部门下所有的员工;在配置文件中有加入cascade="save-update",进行级联保存跟新
        session.getTransaction().commit();
        session.close();
        }
}
保存成功。
/*  sql:
Hibernate: insert into t_dept (deptName) values (?)
Hibernate: insert into t_employee (empName, salary, dept_id) values (?, ?, ?)
Hibernate: insert into t_employee (empName, salary, dept_id) values (?, ?, ?)
Hibernate: update t_employee set dept_id=? where empId=?
Hibernate: update t_employee set dept_id=? where empId=?
*/

2.多对一单向关联;从多的一方保存
配置:多对一单向关联,顾名思义,就是在多的一方Employee保存,以及维护关系,所以在上面Dept类中可以设置private Set emps = new HashSet();该集合属性,映射文件也响删除该配置。
注:这里只贴出测试方法,类名和类的变量和上面一致

@Test
    public void save4() {           
        Session session = sf.openSession();
        session.beginTransaction();         
        // 部门对象
        Dept dept = new Dept();
        dept.setDeptName("应用开发部");
        // 员工对象
        Employee emp_zs = new Employee();
        emp_zs.setEmpName("张三2");
        Employee emp_ls = new Employee();
        emp_ls.setEmpName("李四2");
        // 关系,多的一方维护
        emp_zs.setDept(dept);
        emp_ls.setDept(dept);
        // 保存
        session.save(emp_zs);//在映射文件中一定要配置casecade="save-update",否则不能实现关系的维护
        session.save(emp_ls);           
        session.getTransaction().commit();
        session.close();
    }
保存成功,可以看出从多的一方保存,可以省去两条update语句。所以一般由多的一方维护关系,即在一的一方Dept中,set标签中设置inverse="true"
/*
Hibernate: insert into t_dept (deptName) values (?)
Hibernate: insert into t_employee (empName, salary, dept_id) values (?, ?, ?)
Hibernate: insert into t_employee (empName, salary, dept_id) values (?, ?, ?)
*/

3一对多单向关联
配置:在Employ实体类中可以删除, private Dept dept;该属性,相应的在映射文件中也删除配置,
注:实际上跟上面第一个测试是一样的测试代码,不同点是在配置文件上

@Test
    public void save3() {       
        Session session = sf.openSession();
        session.beginTransaction();     
        // 部门对象
        Dept dept = new Dept();
        dept.setDeptName("应用开发部");
        // 员工对象
        Employee emp_zs = new Employee();
        emp_zs.setEmpName("张三2");
        Employee emp_ls = new Employee();
        emp_ls.setEmpName("李四2");
        // 关系
        dept.getEmps().add(emp_zs);
        dept.getEmps().add(emp_ls);
        // 保存   
        session.save(dept); // 保存部门,部门下所有的员工        
        session.getTransaction().commit();
        session.close();
    }
/*
Hibernate: insert into t_dept (deptName) values (?)
Hibernate: insert into t_employee (empName, salary) values (?, ?)
Hibernate: insert into t_employee (empName, salary) values (?, ?)
Hibernate: update t_employee set dept_id=? where empId=?
Hibernate: update t_employee set dept_id=? where empId=?
*/

总结:
1 没有设置cascade属性的话,在任何一方保存都会出现这个异常,因为在以一方维护,必须具有级联保存的权限

org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing:

2 在一对多单向关联单向关联中,设置了cascade=”save-update”外,不能将inverse设置为true,这个属性的作用是将控制权反转,默认为false,因为没了控制权,也就不能维护关联关系了

  1. 一对多的关系体现得最彻底的是父与子的关系,也就是一个父亲对应多个儿子,多个儿子对应一个父亲,儿子一定有父亲,父不一定有子。所以从这个关系上来说应该是以多的一方来维护关系,所以测试的第三个例子一般很少用,即单向一对多。

以上是自己的总结,如有疑问欢迎吐槽,渴望碰撞。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值