hibernate(2)(一)(映射详解,一对多,多对多)

配置概要:

一对多:
         <set name="映射的集合属性" table="(可选)集合属性对应的外键表">
            <key column="外键表的,外键字段" />
            <one-to-many class="集合元素的类型" />
         </set>
多对一:
         <many-to-one name="对象属性" class="对象类型" column="外键字段字段" />

多对多:
        <set name="" table="">
            <key column="" />
           <many-to-many column="" class="">
        </set>

1.简单容器映射(从表除了外键只有单个字段或者键值字段)

   (集合的元素是基本数据类型)

下面是不同容器生成一个从属表的例子(主键做从表的外键进行关联)

hibernate.cfg.xml

<!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节点代表一个数据库 -->
    <session-factory>
    
        <!-- 1. 数据库连接配置 -->
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.url">jdbc:mysql:///hib_demo</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.connection.password">root</property>
        <!-- 
            数据库方法配置, hibernate在运行的时候,会根据不同的方言生成符合当前数据库语法的sql
         -->
        <property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
        
        
        <!-- 2. 其他相关配置 -->
        <!-- 2.1 显示hibernate在运行时候执行的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. 加载所有映射 <mapping resource="cn/it/Employee.hbm.xml"/>-->
    </session-factory>
</hibernate-configuration>
View Code

User.java

public class User {
    private int userId;
    private String userName;
    // 一个用户,对应的多个地址
    private Set<String> address;
    private List<String> addressList = new ArrayList<String>(); 
    //private String[] addressArray; // 映射方式和list一样     <array name=""></array>
    private Map<String,String> addressMap = new HashMap<String, String>();
    public Map<String, String> getAddressMap() {
        return addressMap;
    }
    public void setAddressMap(Map<String, String> addressMap) {
        this.addressMap = addressMap;
    }
    public List<String> getAddressList() {
        return addressList;
    }
    public void setAddressList(List<String> addressList) {
        this.addressList = addressList;
    }
    public int getUserId() {
        return userId;
    }
    public void setUserId(int userId) {
        this.userId = userId;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    public Set<String> getAddress() {
        return address;
    }
    public void setAddress(Set<String> address) {
        this.address = address;
    }    
}
View Code

User.hbm.xml

<?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="cn.itcast.a_collection">
    
    <class name="User" table="t_user">
        <id name="userId" column="id">
            <generator class="native"></generator>
        </id>    
        <property name="userName"></property>
        
        <!-- 
            set集合属性的映射
                name 指定要映射的set集合的属性
                table 集合属性要映射到的表
                key  指定集合表(t_address)的外键字段
                element 指定集合表的其他字段
                    type 元素类型,一定要指定
         -->
         <set name="address" table="t_address">
             <key column="uid"></key>
             <element column="address" type="string"></element>
         </set>
         
         <!-- 
             list集合映射
                 list-index  指定的是排序列的名称 (因为要保证list集合的有序)
          -->
          <list name="addressList" table="t_addressList">
                <key column="uid"></key>
                <list-index column="idx"></list-index>
                <element column="address" type="string"></element>
          </list>
          
          <!-- 
              map集合的映射
                  key  指定外键字段
                  map-key 指定map的key 
                  element  指定map的value
           -->
          <map name="addressMap" table="t_addressMap">
              <key column="uid"></key>
              <map-key column="shortName" type="string" ></map-key>
              <element column="address" type="string" ></element>
          </map>
    </class>
</hibernate-mapping>
View Code

测试类:

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

    // 保存set
    @Test
    public void testSaveSet() throws Exception {
        Session session = sf.openSession();
        session.beginTransaction();
        
        //-- 保存
        Set<String> addressSet = new HashSet<String>();
        addressSet.add("广州");
        addressSet.add("深圳");
        // 用户对象
        User user = new User();
        user.setUserName("Jack");
        user.setAddress(addressSet);
        
        // 保存
        session.save(user);
        
        session.getTransaction().commit();
        session.close();
    }
    
    // 保存list/map
    @Test
    public void testSaveList() throws Exception {
        Session session = sf.openSession();
        session.beginTransaction();
        User user = new User();
        user.setUserName("Tom");
//        // 用户对象  --  list
//        user.getAddressList().add("广州");
//        user.getAddressList().add("深圳");
//        // 保存
//        session.save(user);
        
        // 用户对象  --  Map
        user.getAddressMap().put("A0001", "广州");
        user.getAddressMap().put("A0002", "深圳");
        
        // 保存
        session.save(user);
        
        session.getTransaction().commit();
        session.close();
    }
    
    // 获取
    @Test
    public void testGet() throws Exception {
        Session session = sf.openSession();
        session.beginTransaction();
        
        // 获取
        User user = (User) session.get(User.class, 3); // 及时加载
        System.out.println(user.getUserId());
        System.out.println(user.getUserName());
        
        // 当查询用户,同时可以获取用户关联的list集合的数据 (因为有正确映射)
        // 当使用到集合数据的使用,才向数据库发送执行的sql语句  (懒加载)
        System.out.println(user.getAddressList());
        
        session.getTransaction().commit();
        session.close();
    }}
View Code

 

多对一映射与一对多(如果两边都配置即是双向关联,只配置一个就单向)

部门与员工:
          一个部门有多个员工;       【一对多】
          多个员工,属于一个部门    【多对一】

一对多关联映射配置  (通过部门管理到员工)
            Dept 映射关键点:
            1.  指定 映射的集合属性: "emps"
            2.  集合属性对应的集合表: "t_employee"
            3.  集合表的外键字段   "t_employee. dept_id"
            4.  集合元素的类型
多对一映射配置
            Employee 映射关键点:
            1.  映射的部门属性  :  dept
            2.  映射的部门属性,对应的外键字段: dept_id
            3.  部门的类型

下面是一个双向关联的例子:(用的最多的还是单向多对一的情况)

Dept.java

public class Dept {
    private int deptId;
    private String deptName;
    // 【一对多】 部门对应的多个员工
    private Set<Employee> emps = new HashSet<Employee>();
    
    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> getEmps() {
        return emps;
    }
    public void setEmps(Set<Employee> emps) {
        this.emps = emps;
    }
View Code

Dept.hbm.xml(映射中可以省略表名,因为可以通过类找到对应映射得到表名)

<?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="cn.itcast.b_one2Many">
    
    <class name="Dept" table="t_dept">
        <id name="deptId">
            <generator class="native"></generator>
        </id>    
        <property name="deptName" length="20"></property>
        
        <!-- 
            一对多关联映射配置  (通过部门管理到员工)
            Dept 映射关键点:
            1.  指定 映射的集合属性: "emps"
            2.  集合属性对应的集合表: "t_employee"
            3.  集合表的外键字段   "t_employee. dept_id"
            4.  集合元素的类型
            
            inverse=false  set集合映射的默认值; 表示有控制权
         -->
         <set name="emps" cascade="save-update,delete" table="t_employee" inverse="true">   <!-- table="t_employee" -->
              <key column="dept_id"></key>
              <one-to-many class="Employee"/>
         </set>                  
    </class>    
</hibernate-mapping>
View Code

Employee.java(设置外键步骤1.代码中属性是该外键对应表的对象)

public class Employee {
    private int empId;
    private String empName;
    private double salary;
    // 【多对一】员工与部门
    private 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;
    }
    public Dept getDept() {
        return dept;
    }
    public void setDept(Dept dept) {
        this.dept = dept;
    }
View Code

Employee.hbm.xml(设置外键步骤2.配置中many-to-one 标签中声明字段)

<?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="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>        
        <!-- 
            多对一映射配置
            Employee 映射关键点:
            1.  映射的部门属性  :  dept
            2.  映射的部门属性,对应的外键字段: dept_id
            3.  部门的类型
         -->
         <many-to-one name="dept" column="dept_id" class="Dept"></many-to-one>         
    </class>    
</hibernate-mapping>
View Code

测试类:

保存:

(在保存时,设置对象的关联方式以及保存的顺序不一样,执行sql语句也是不一样的:
一种是:将对象关联的方式设置在1上(一个部门对应多个员工的属性集合上,这个属性在主表中并没有实际的字段对应,只是从表外键,这样会执行所有插入后再执行这种关联的更新语句。
另一种:将对象关联的方式设置在多上(每个员工设置一个部门,即在外键上,如果先执行保存部门那么就会得到部门外键,保存员工后(对象中已经有关联的部门了),就不用执行更新语句。如果先执行保存员工再保存部门,那么之后还是得执行更新操作。

第二种的前一种方式能够减少sql语句的执行。(一对多的情况,由多的一方来维护关系)

public class Test {
    
    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.getEmps().add(emp_zs);
        dept.getEmps().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 deptId=? where empId=?    维护员工引用的部门的id
            Hibernate: update t_employee set deptId=? 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_zs);
        session.save(emp_ls);// 再保存多的一方,关系回自动维护(映射配置完)
        
        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 (?, ?, ?)
            少生成2条update  sql
         */
    }
View Code

获取:获取对象的时候,其关联的对象是调用具体方法才执行的(懒加载)

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.getEmps());// 懒加载        
        
        // 通过员工房,获取另外一方
        Employee emp = (Employee) session.get(Employee.class, 1);
        System.out.println(emp.getEmpName());
        System.out.println(emp.getDept().getDeptName());
                
        session.getTransaction().commit();
        session.close();
    }
View Code

关于inverse属性:

是在维护关联关系的时候起作用的。
表示控制权是否转移。(在一的一方起作用)
Inverse = false(默认)  不反转;   当前方有控制权
          True          控制反转; 当前方没有控制权

维护关联关系中的具体影响:

1. 保存数据的影响。

    如果inverse=true, 然后通过部门方维护关联关系。

    在保存部门的时候,同时保存员工, 数据会保存,但关联关系不会维护(不会执行外键值更新语句)。即外键字段为NULL

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.getEmps().add(emp_zs);
        dept.getEmps().add(emp_ls);  // inverse=true,  不会设置关联。             
        
        // 保存
        session.save(emp_zs);
        session.save(emp_ls);
        session.save(dept); // 保存部门,部门下所有的员工          
        session.getTransaction().commit();
        session.close();
    }

数据库效果:

2. 获取数据不会有影响:

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.getEmps());
        
        session.getTransaction().commit();
        session.close();
    }

3. 解除关联关系的影响:(即修改关联表的外键值)

      inverse=false,  可以解除关联 (会执行查询部门,再查询员工,再执行更新员工的外键为null)

      inverse=true,  当前方(部门)没有控制权,不能解除关联关系

                           (不会生成update语句,程序也不会提示报错)

public void removeRelation() {
        Session session = sf.openSession();
        session.beginTransaction();
        
        // 获取部门
        Dept dept = (Dept) session.get(Dept.class, 2);
        // 解除关系
        dept.getEmps().clear();
        
        session.getTransaction().commit();
        session.close();
    }

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

   (补充:一般有外键关联的数据,是不能直接删除主键的,需要先删除外键对应的纪录或者将外键置为null)

     inverse=false, 有控制权, 可以删除。先清空外键引用,再删除数据。

     inverse=true,  没有控制权: 如果删除的记录有被外键引用,会报错,违反主外键引用约束! 

                         如果删除的记录没有被引用,可以直接删除。

public void deleteData() {
        Session session = sf.openSession();
        session.beginTransaction();        
        // 查询部门
        Dept dept = (Dept) session.get(Dept.class, 8);
        session.delete(dept);
                
        session.getTransaction().commit();
        session.close();

当为false时候会首先执行修改外键值再更新:

当为true会直接执行执行删除主键纪录,会报错:

cascade  表示级联操作  【可以设置到一的一方或多的一方】

         none               不级联操作, 默认值
         save-update        级联保存或更新
         delete             级联删除
         save-update,delete 级联保存、更新、删除
         all                同上。级联保存、更新、删除

保存:

不使用级联属性:(代码中还要写保存关联对象)

         // 保存
        session.save(emp_zs);
        session.save(emp_ls);
        session.save(dept); //

使用级联保存属性:(代码中不用写保存关联对象,效果同上)

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.getEmps().add(emp_zs);
        dept.getEmps().add(emp_ls);  
        
        // 保存
        session.save(dept); // 需要设置级联保存; 保存部门,部门下所有的员工  
        
        session.getTransaction().commit();
        session.close();
    }

更新:(一般没有改主键需求)

删除:

默认删除只是把关联纪录的外键置为null,然后删除主键记录:

级联删除:将主键和外键对应的记录都删除了(一般不设置级联删除,采用手动分别删除,以防万一删了多余的)

public void delete() {
        Session session = sf.openSession();
        session.beginTransaction();
        
        Dept dept = (Dept) session.get(Dept.class,7);
        session.delete(dept); // 级联删除
        
        session.getTransaction().commit();
        session.close();
    }

 当级联和控制反转同时使用在删除的时候,是可以删除的,只是执行语句不同(没有更新语句):

注意:inverse和cascade的区别:控制反转针对的关联关系的修改(针对对关联外键的影响,并且只能在一的一方);级联是针对关联数据的影响

 

多对多映射:

需求:项目与开发人员(项目和人员存在交叉的关系,一个项目对于多个人员,该人员又对于多个项目)

 Project   Developer
               曹吉
 电商系统       王春
           
               王春
 OA系统         老张                        

数据库效果:关联关系表是通过关联关系配置实现的。

Project.java

public class Project {
    private int prj_id;
    private String prj_name;
    // 项目下的多个员工
    private Set<Developer> developers = new HashSet<Developer>();        
    public int getPrj_id() {
        return prj_id;
    }
    public void setPrj_id(int prjId) {
        prj_id = prjId;
    }
    public String getPrj_name() {
        return prj_name;
    }
    public void setPrj_name(String prjName) {
        prj_name = prjName;
    }
    public Set<Developer> getDevelopers() {
        return developers;
    }
    public void setDevelopers(Set<Developer> developers) {
        this.developers = developers;
    }
View Code

Project.hbm.xml(配置中维护关系表)

<?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="cn.itcast.c_many2many">
    
    <class name="Project" table="t_project">
        <id name="prj_id">
            <generator class="native"></generator>
        </id>    
        <property name="prj_name" length="20"></property>
        <!-- 
            多对多映射:
            1.  映射的集合属性: “developers”
            2.  集合属性,对应的中间表: “t_relation”
            3. 外键字段:  prjId
            4. 外键字段,对应的中间表字段:  did
            5.   集合属性元素的类型
         -->
         <set name="developers" table="t_relation" cascade="save-update" inverse="true">
             <key column="prjId"></key>
             <many-to-many column="did" class="Developer"></many-to-many>
         </set>
         
    </class>    
</hibernate-mapping>
View Code

Developer.java

public class Developer {
    private int d_id;
    private String d_name;
    // 开发人员,参数的多个项目
    private Set<Project> projects = new HashSet<Project>();
    
    
    public int getD_id() {
        return d_id;
    }
    public void setD_id(int dId) {
        d_id = dId;
    }
    public String getD_name() {
        return d_name;
    }
    public void setD_name(String dName) {
        d_name = dName;
    }
    public Set<Project> getProjects() {
        return projects;
    }
    public void setProjects(Set<Project> projects) {
        this.projects = projects;
    }
View Code

Developer.hbm.xml

<?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="cn.itcast.c_many2many">
    
    <class name="Developer" table="t_developer">
        <id name="d_id">
            <generator class="native"></generator>
        </id>    
        <property name="d_name" length="20"></property>
        
        <!-- 
            多对多映射配置: 员工方
                name  指定映射的集合属性
                table 集合属性对应的中间表
                key   指定中间表的外键字段(引用当前表t_developer主键的外键字段)
                many-to-many
                    column 指定外键字段对应的项目字段
                    class  集合元素的类型
         -->
        <set name="projects" table="t_relation">
            <key column="did"></key>
            <many-to-many column="prjId" class="Project"></many-to-many>
        </set>
                 
    </class>    
</hibernate-mapping>
View Code

测试类:

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

    // 1. 多对多,保存  【只能通过一方维护另外一方,不能重复维护!】
    @Test
    public void save() {
        Session session = sf.openSession();
        session.beginTransaction();        
        /*
         * 模拟数据: 
           电商系统(曹吉,王春)
           OA系统(王春,老张)
         */
        // 创建项目对象
        Project prj_ds = new Project();
        prj_ds.setPrj_name("电商系统");
        Project prj_oa = new Project();
        prj_oa.setPrj_name("OA系统");
        
        // 创建员工对象
        Developer dev_cj = new Developer();
        dev_cj.setD_name("曹吉");
        Developer dev_wc = new Developer();
        dev_wc.setD_name("王春");
        Developer dev_lz = new Developer();
        dev_lz.setD_name("老张");
        // 关系 【项目方】 关联关系只能在一方添加!!!
        prj_ds.getDevelopers().add(dev_cj);
        prj_ds.getDevelopers().add(dev_wc); // 电商系统(曹吉,王春)
        prj_oa.getDevelopers().add(dev_wc);
        prj_oa.getDevelopers().add(dev_lz); // OA系统(王春,老张)        
        
         // 保存
         session.save(dev_cj);
         session.save(dev_wc);
         session.save(dev_lz);        
        session.save(prj_ds);
        session.save(prj_oa);   // 也可以设置级联保存(配置cascade属性),只需要保存项目的一方,会自动通过关系保存人员
        
        session.getTransaction().commit();
        session.close();
    }

产生的语句;

inverse在多对多关系关系的维护产生的影响:

保存的影响:true,关联关系表的数据没有进行维护

public void save() {
        Session session = sf.openSession();
        session.beginTransaction();            
        // 创建项目对象
        Project prj_ds = new Project();
        prj_ds.setPrj_name("电商系统");
        Project prj_oa = new Project();
        prj_oa.setPrj_name("OA系统");
        
        // 创建员工对象
        Developer dev_cj = new Developer();
        dev_cj.setD_name("曹吉");
        Developer dev_wc = new Developer();
        dev_wc.setD_name("王春");
        Developer dev_lz = new Developer();
        dev_lz.setD_name("老张");
        // 关系 【项目方】
        prj_ds.getDevelopers().add(dev_cj);
        prj_ds.getDevelopers().add(dev_wc); // 电商系统(曹吉,王春)
        prj_oa.getDevelopers().add(dev_wc);
        prj_oa.getDevelopers().add(dev_lz); // OA系统(王春,老张)
        
        session.save(prj_ds);
        session.save(prj_oa);   // 必须要设置级联保存         
        session.getTransaction().commit();
        session.close();
    }

数据库执行效果

获取没有影响:

        Project prj = (Project) session.get(Project.class, 1);
        System.out.println(prj.getPrj_name());
        System.out.println(prj.getDevelopers());

解除关系有影响:

false时,解除关系是删除关联关系(和一对多不同,那个是置为null):

        Project prj = (Project) session.get(Project.class, 7);
        prj.getDevelopers().clear();        

inverse=true, 没有控制权,不能解除关系(只执行查询语句)

删除有影响:

inverse=false, 有控制权。 先删除中间表数据,再删除自身(只删除自身和关联关系,没有去删除关联的数据)。(和一对多关联关系不同,那个还将外键对应的数据也删除)

        Project prj = (Project) session.get(Project.class, 1);
        session.delete(prj);

nverse=true, 没有控制权。 如果删除的数据有被引用,会报错! 否则,才可以删除

会直接执行删除,没有处理外键,程序会报错。

 

 

 

 

posted @ 2017-03-17 19:05  假程序猿  阅读(221)  评论(0)    收藏  举报