Hibernate学习-7-关联映射(一对多,多对一)

关联映射

需求分析

 

eg 1-

  部门与员工的例子

        一个部门有多个员工[一对多]

        多个员工,属于一个部门[多对一]

eg 2-

       一个项目多个开发人员

       一个开发人员参与多个项目 [多对多]

 

一对多与多对一映射

一.需求分析

二.数据库

t_dept

字段:deptId  deptName 

t_employee

字段:empId empName salary dept_id

三.javabean

设计关键:通过一方维护到另一方

class Dept{
   
    private int deptId;
    
    private String deptName;

    //部门对应多个员工
    private Set<Employee> emps;

}

class Employee{
    
   private int empId;
   
   private String empName;

   private double salary;
 
   //多个员工对应一个部门
   private Dept dept;
}

四.映射

Dept映射关键点

1.映射的集合属性:"emps"

2.指定集合属性对应的集合表:"t_employee"

3.指定集合表的外键字段

4.指定集合元素的类型

 Employee映射的关键点

1.映射的部门属性: dept

2.映射的部门对象,对应的外键字段:dept_id

3.部门的类型

实例-保存数据-查询数据

总配置文件

<!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>
         <!--1.数据库连接配置-->
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.url">jdbc:mysql:///learnHibernate</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.connection.password">33269456.cx</property>
        <!--
          数据库方言配置,hibernate会根据不同的方言生成符合当前数据库语法的sql
        -->
        <property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>

        <!--2.其他相关配置-->
        <!--2.1显示运行时的sql语句-->
        <property name="hibernate.show_sql">true</property>


        <!--2.2格式化sql-->


        <property name="hibernate.format_sql">true</property>


        <!--2.3自动建表,写好映射就可以-->

        <property name="hibernate.hbm2ddl.auto">update</property>

        <!--3.加载所有映射-->

    </session-factory>

</hibernate-configuration>

Dept.java

package com.cx.entity;

import java.util.HashSet;
import java.util.Set;

/**
 * Created by cxspace on 16-8-2.
 */
public class Dept {


    private int deptId;

    private String deptName;

    //一对多(一个部门对应多个员工)
    private Set<Employee> employees = new HashSet<>();

    public int getDeptId() {
        return deptId;
    }

    public void setDeptId(int deptId) {
        this.deptId = deptId;
    }

    public String getDeptName() {
        return deptName;
    }

    public void setDeptName(String deptName) {
        this.deptName = deptName;
    }

    public Set<Employee> getEmployees() {
        return employees;
    }

    public void setEmployees(Set<Employee> employees) {
        this.employees = employees;
    }
}

相关映射配置

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">


<hibernate-mapping package="com.cx.entity">


    <class name="Dept" table="t_dept">

        <id name="deptId">
            <generator class="native"></generator>
        </id>

        <property name="deptName" length="20"></property>

        <!--
            1.映射的集合属性:"emps"

            2.指定集合属性对应的集合表:"t_employee"

            3.指定集合表的外键字段

            4.指定集合元素的类型
        -->

        <!--table="t_employee",可以省略-->

        <set name="employees" table="t_employee">
            <key column="dept_id"></key>
            <one-to-many class="Employee"></one-to-many>
        </set>


    </class>

</hibernate-mapping>

Employee.java

package com.cx.entity;

/**
 * Created by cxspace on 16-8-2.
 */
public class Employee {

    private int empId;

    private String empName;

    private double salary;

    private Dept dept;

    public Dept getDept() {
        return dept;
    }

    public void setDept(Dept dept) {
        this.dept = dept;
    }

    public int getEmpId() {
        return empId;
    }

    public void setEmpId(int empId) {
        this.empId = empId;
    }

    public String getEmpName() {
        return empName;
    }

    public void setEmpName(String empName) {
        this.empName = empName;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }
}

相关映射配置

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">


<hibernate-mapping package="com.cx.entity">

    <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>

        <!--
        多对一映射配置
        Employee 映射关键点:
        1.  映射的部门属性  :  dept
        2.  映射的部门属性,对应的外键字段: dept_id
        3.  部门的类型
        -->

        <many-to-one name="dept" column="dept_id" class="Dept"></many-to-one>

    </class>

</hibernate-mapping>

测试类

package com.cx.test;

import com.cx.entity.Dept;
import com.cx.entity.Employee;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.Test;

/**
 * Created by cxspace on 16-8-2.
 */
public class Save {

    private static SessionFactory sf;
    static {
        sf = new Configuration()
                .configure()
                .addClass(Dept.class)
                .addClass(Employee.class)   // 测试时候使用
                .buildSessionFactory();
    }


    //保存,部门方 一对一方法操作

    public void save(){

        Session session = sf.openSession();
        session.beginTransaction();

        //部门对象
        Dept dept = new Dept();
        dept.setDeptName("应用开发部");

        //员工对象
        Employee emp_zs = new Employee();

        emp_zs.setEmpName("张三");

        Employee emp_ls = new Employee();

        emp_ls.setEmpName("李四");

        //关系
        dept.getEmployees().add(emp_zs);
        dept.getEmployees().add(emp_ls);

        //保存

        session.save(emp_zs);
        session.save(emp_ls);

        session.save(dept);

        session.getTransaction().commit();
        session.close();

        /*
        *

                Hibernate:
                    insert
                    into
                        t_employee
                        (empName, salary, dept_id)
                    values
                        (?, ?, ?)
                Hibernate:
                    insert
                    into
                        t_employee
                        (empName, salary, dept_id)
                    values
                        (?, ?, ?)
                Hibernate:
                    insert
                    into
                        t_dept
                        (deptName)
                    values
                        (?)
                Hibernate:
                    update
                        t_employee
                    set
                        dept_id=?
                    where
                        empId=?
                Hibernate:
                    update
                        t_employee
                    set
                        dept_id=?
                    where
                        empId=?

        * */

    }


    //保存,员工方[多对一保存],效率更高
    @Test

    public void save2(){

        Session session = sf.openSession();
        session.beginTransaction();

        Dept dept = new Dept();
        dept.setDeptName("综合部");

        Employee emp_zs = new Employee();
        emp_zs.setEmpName("张三");

        Employee emp_ls = new Employee();
        emp_ls.setEmpName("李四");

        emp_zs.setDept(dept);
        emp_ls.setDept(dept);

        session.save(dept);
        session.save(emp_ls);
        session.save(emp_zs);

        session.getTransaction().commit();
        session.close();

        /*
        *
        * 结果
        *
        *   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
                    (?, ?, ?)
        *
        *
        * */

    }

}

结果

package com.cx.test;

import com.cx.entity.Dept;
import com.cx.entity.Employee;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.Test;

/**
 * Created by cxspace on 16-8-2.
 */
public class Get {


    private static SessionFactory sf;
    static {
        sf = new Configuration()
                .configure()
                .addClass(Dept.class)
                .addClass(Employee.class)   // 测试时候使用
                .buildSessionFactory();
    }

    @Test
    public void get(){

        Session session = sf.openSession();
        session.beginTransaction();

        //通过部门方获取另一方
//        Dept dept = (Dept) session.get(Dept.class , 1);
//        System.out.println(dept.getDeptName());
//        System.out.println(dept.getEmployees());


结果

Hibernate:
select
dept0_.deptId as deptId0_0_,
dept0_.deptName as deptName0_0_
from
t_dept dept0_
where
dept0_.deptId=?
应用开发部
Hibernate:
select
employees0_.dept_id as dept4_0_1_,
employees0_.empId as empId1_,
employees0_.empId as empId1_0_,
employees0_.empName as empName1_0_,
employees0_.salary as salary1_0_,
employees0_.dept_id as dept4_1_0_
from
t_employee employees0_
where
employees0_.dept_id=?
[com.cx.entity.Employee@d35dea7, com.cx.entity.Employee@24313fcc]


//通过员工获取部门 Employee emp = (Employee)session.get(Employee.class,1); System.out.println(emp.getEmpName()); System.out.println(emp.getDept().getDeptName()); session.getTransaction().commit(); session.close();

结果

Hibernate:
select
employee0_.empId as empId1_0_,
employee0_.empName as empName1_0_,
employee0_.salary as salary1_0_,
employee0_.dept_id as dept4_1_0_
from
t_employee employee0_
where
employee0_.empId=?
张三
Hibernate:
select
dept0_.deptId as deptId0_0_,
dept0_.deptName as deptName0_0_
from
t_dept dept0_
where
dept0_.deptId=?
应用开发部



    }

}

 

Inverse属性

在维护关联关系的时候起作用。表示控制权是否转移。(在一的一方起作用)

inverse 控制反转

inverse = false不反转          有控制权    

            = true 控制反转        没有控制权 (不能主动维护另一方)

 

维护关联关系

1.保存数据

     设计关联

     如果设置控制反转,然后通过部门方维护关联关系。在保存部门的时候,同时保存员工,数据会保存,但关联关系不会维护,外键字段为NULL。

2.获取数据

     无影响

3.解除关联关系

     有影响

     没有控制权无法接触关联关系,无法生成update语句,也不会报错

4.删除数据对关联关系的影响

  有控制权,可以删除,先清空外键引用,再删除。

  没控制权报错,无法删除。

测试代码

package com.cx.test;

import com.cx.entity.Dept;
import com.cx.entity.Employee;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.Test;

/**
 * Created by cxspace on 16-8-2.
 */
public class Inverse {

    private static SessionFactory sf;
    static {
        sf = new Configuration()
                .configure()
                .addClass(Dept.class)
                .addClass(Employee.class)   // 测试时候使用
                .buildSessionFactory();
    }


    //inverse对保存数据的影响
    public void save(){

        Session session = sf.openSession();
        session.beginTransaction();

        //部门对象
        Dept dept = new Dept();
        dept.setDeptName("运维部");

        //员工对象
        Employee emp_zs = new Employee();

        emp_zs.setEmpName("张三");

        Employee emp_ls = new Employee();

        emp_ls.setEmpName("李四");

        //关系
        dept.getEmployees().add(emp_zs);
        dept.getEmployees().add(emp_ls);

        //inverse = true ,不会设置关联,此时的关联应该通过员工方来维护

        //保存

        session.save(emp_zs);
        session.save(emp_ls);

        session.save(dept);

        session.getTransaction().commit();
        session.close();


        /*
        *
        *
        *
        Hibernate:
            insert
            into
                t_employee
                (empName, salary, dept_id)
            values
                (?, ?, ?)
        Hibernate:
            insert
            into
                t_employee
                (empName, salary, dept_id)
            values
                (?, ?, ?)
        Hibernate:
            insert
            into
                t_dept
                (deptName)
            values
                (?)
                *
                *
                * */

            }

    //inverse属性,对获取数据的影响---无影响


    public void get(){
        Session session = sf.openSession();
        session.beginTransaction();

        Dept dept = (Dept) session.get(Dept.class,2);

        System.out.println(dept.getDeptName());
        System.out.println(dept.getEmployees());

        session.getTransaction().commit();
        session.close();

        /*
        *
        *
        *
        * Hibernate:
    select
        dept0_.deptId as deptId0_0_,
        dept0_.deptName as deptName0_0_
    from
        t_dept dept0_
    where
        dept0_.deptId=?
综合部
Hibernate:
    select
        employees0_.dept_id as dept4_0_1_,
        employees0_.empId as empId1_,
        employees0_.empId as empId1_0_,
        employees0_.empName as empName1_0_,
        employees0_.salary as salary1_0_,
        employees0_.dept_id as dept4_1_0_
    from
        t_employee employees0_
    where
        employees0_.dept_id=?
[com.cx.entity.Employee@d35dea7, com.cx.entity.Employee@24313fcc]
        *
        *
        *
        *
        *
        *
        *
        * */

    }


    public void removeRelation(){

        Session session = sf.openSession();
        session.beginTransaction();

        Dept dept = (Dept)session.get(Dept.class,2);

        dept.getEmployees().clear();

        session.getTransaction().commit();
        session.close();

        /*
        * inverse=true 没有控制权
        *
        *
   Hibernate:
    select
        dept0_.deptId as deptId0_0_,
        dept0_.deptName as deptName0_0_
    from
        t_dept dept0_
    where
        dept0_.deptId=?
        *
        *
        *
        inverse = false

     Hibernate:
    select
        dept0_.deptId as deptId0_0_,
        dept0_.deptName as deptName0_0_
    from
        t_dept dept0_
    where
        dept0_.deptId=?
Hibernate:
    select
        employees0_.dept_id as dept4_0_1_,
        employees0_.empId as empId1_,
        employees0_.empId as empId1_0_,
        employees0_.empName as empName1_0_,
        employees0_.salary as salary1_0_,
        employees0_.dept_id as dept4_1_0_
    from
        t_employee employees0_
    where
        employees0_.dept_id=?
Hibernate:
    update
        t_employee
    set
        dept_id=null
    where
        dept_id=?


        *
        * */

    }

    @Test
    public void deleteData(){
        Session session = sf.openSession();
        session.beginTransaction();


        Dept dept = (Dept) session.get(Dept.class,1);
        session.delete(dept);

        session.getTransaction().commit();
        session.close();

        /*
        inverse = true
        Hibernate:

            select
                dept0_.deptId as deptId0_0_,
                dept0_.deptName as deptName0_0_
            from
                t_dept dept0_
            where
                dept0_.deptId=?
        Hibernate:
            delete
            from
                t_dept
            where
                deptId=?

                报错
            org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update

    at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:96)
    at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
    at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:275)
    at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:268)
    at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:189)
    at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
    at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51)
    at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1216)
    at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:383)
    at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:133)
    at com.cx.test.Inverse.deleteData(Inverse.java:217)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.internal.runners.TestMethodRunner.executeMethodBody(TestMethodRunner.java:99)
    at org.junit.internal.runners.TestMethodRunner.runUnprotected(TestMethodRunner.java:81)
    at org.junit.internal.runners.BeforeAndAfterRunner.runProtected(BeforeAndAfterRunner.java:34)
    at org.junit.internal.runners.TestMethodRunner.runMethod(TestMethodRunner.java:75)
    at org.junit.internal.runners.TestMethodRunner.run(TestMethodRunner.java:45)
    at org.junit.internal.runners.TestClassMethodsRunner.invokeTestMethod(TestClassMethodsRunner.java:66)
    at org.junit.internal.runners.TestClassMethodsRunner.run(TestClassMethodsRunner.java:35)
    at org.junit.internal.runners.TestClassRunner$1.runUnprotected(TestClassRunner.java:42)
    at org.junit.internal.runners.BeforeAndAfterRunner.runProtected(BeforeAndAfterRunner.java:34)
    at org.junit.internal.runners.TestClassRunner.run(TestClassRunner.java:52)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:130)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:119)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:234)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:74)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
Caused by: java.sql.BatchUpdateException: Cannot delete or update a parent row: a foreign key constraint fails (`learnHibernate`.`t_employee`, CONSTRAINT `FKFDCF5A195CFBCEF9` FOREIGN KEY (`dept_id`) REFERENCES `t_dept` (`deptId`))
    at com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:2054)
    at com.mysql.jdbc.PreparedStatement.executeBatch(PreparedStatement.java:1467)
    at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70)
    at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:268)
    ... 32 more


                inverse = false

                正常删除
                
            Hibernate: 
                select
                    dept0_.deptId as deptId0_0_,
                    dept0_.deptName as deptName0_0_ 
                from
                    t_dept dept0_ 
                where
                    dept0_.deptId=?
            Hibernate: 
                update
                    t_employee 
                set
                    dept_id=null 
                where
                    dept_id=?
            Hibernate: 
                delete 
                from
                    t_dept 
                where
                    deptId=?    
                            

         */

    }

}

 

cascade属性

表示级联操作

none不级联操作 ,默认值

save-update级联保存或者更新

delete级联删除

save-update,delete 级联保存、更新、删除

all    同上

实例

package com.cx.test;

import com.cx.entity.Dept;
import com.cx.entity.Employee;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.Test;

/**
 * Created by cxspace on 16-8-2.
 */
public class Cascade {

    private static SessionFactory sf;
    static {
        sf = new Configuration()
                .configure()
                .addClass(Dept.class)
                .addClass(Employee.class)   // 测试时候使用
                .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("张三");
        Employee emp_ls = new Employee();
        emp_ls.setEmpName("李四");
        // 关系
        dept.getEmployees().add(emp_zs);
        dept.getEmployees().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, 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=?
        * */


    }

    public void delete(){
        Session session = sf.openSession();
        session.beginTransaction();

        Dept dept = (Dept) session.get(Dept.class,5);

        session.delete(dept);

        session.getTransaction().commit();
        session.close();

        /*
        *
        * Hibernate:
    select
        dept0_.deptId as deptId0_0_,
        dept0_.deptName as deptName0_0_
    from
        t_dept dept0_
    where
        dept0_.deptId=?
Hibernate:
    select
        employees0_.dept_id as dept4_0_1_,
        employees0_.empId as empId1_,
        employees0_.empId as empId1_0_,
        employees0_.empName as empName1_0_,
        employees0_.salary as salary1_0_,
        employees0_.dept_id as dept4_1_0_
    from
        t_employee employees0_
    where
        employees0_.dept_id=?
Hibernate:
    update
        t_employee
    set
        dept_id=null
    where
        dept_id=?
Hibernate:
    delete
    from
        t_employee
    where
        empId=?
Hibernate:
    delete
    from
        t_employee
    where
        empId=?
Hibernate:
    delete
    from
        t_dept
    where
        deptId=?
        *
        * */

    }

}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值