zoukankan      html  css  js  c++  java
  • Hibernate-多表关系

    多表关系映射

    1.一对一(会用即可)

    主表:没有外键 有主键
    从表:拥有外键的是从表
    先操作从表,再去操作主表
    one-to-one  ,many-to-one 只是表达多个表之间的关系。
    外键:目的是多表连接
    主键:目的是唯一标识数据
    1.1 方式一: 按照主键映射 (主键都是一样的)
    用已有的主键充当外键去连接表来表示关系
    方式二:按照外键映射
    给表额外插入一个列作为外键去连接另一个表

    2、一对多|多对一(最常见的,重点掌握)

    示例

    2.1 持久化类
    package com.qf.domain;
    ​
    //从表(拥有外键。)
    public class Contact {
        private Integer contact_id; //主键
        private String contact_name;
        private Integer contact_cust_id;//外键(表达关系的时候声明外键即可)
        private String contact_gender;
        private String contact_phone;
        private String contact_mobile;
        private String contact_email;
        private String contact_qq;
        private String contact_position;
        private String contact_memo;//备注
        //表达多(Contact)对一(Customer)关系
        private Customer customer;
        set/get.....
    }
    package com.qf.domain;
    
    //主表
    public class Customer {
        private Integer  cust_id;//主键
        private String  cust_name;
        private Integer  cust_user_id;
        private Integer  cust_create_id;
        private String  cust_source;
        private String  cust_industry;
        private String  cust_level;
        private String  cust_linkman;
        private String  cust_phone;
        private String  cust_mobile;
        
        //表达一(Customer)对多(Contact)的关系
        private Set<Contact> contacts =new HashSet<>();
        set/get.....
    }
    映射文件  Contact.hbm.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <!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.qf.domain">
        <class name="Contact" table="contact">
            <id name="contact_id">
                <generator class="native"></generator>
            </id>
            <property name="contact_name" ></property>
            <property name="contact_gender" ></property>
            <property name="contact_phone" ></property>
            <property name="contact_mobile" ></property>
            <property name="contact_email" ></property>
            <property name="contact_qq" ></property>
            <property name="contact_position" ></property>
            <property name="contact_memo" ></property>
            
            <!-- 表达多对一关系
             column:声明外键-->
            <many-to-one name="customer" column="contact_cust_id"></many-to-one>    
        </class>
    </hibernate-mapping>    
    ​
    Customer.hbm.xml
    ​
    <?xml version="1.0" encoding="UTF-8"?>
    <!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.qf.domain">
        <class name="Customer" table="customer">
            <id name="cust_id" column="cust_id">
                <generator class="native"></generator>
            </id>
            <property name="cust_name" column="cust_name"></property>
            <property name="cust_user_id" column="cust_user_id"></property>
            <property name="cust_create_id" column="cust_create_id"></property>
            <property name="cust_source" column="cust_source"></property>
            <property name="cust_industry" column="cust_industry"></property>
            <property name="cust_level" column="cust_level"></property>
            <property name="cust_linkman" column="cust_linkman"></property>
            <property name="cust_phone" column="cust_phone"></property>
            <property name="cust_mobile" column="cust_mobile"></property>   
            <!-- 表达一对多的关系 -->
             <set name="contacts">
                <!-- column外键:说明哪一个外键要连接当前的表 -->
               <key column="contact_cust_id"></key>
               <!-- 表达关系 -->
               <one-to-many class="Contact"/>
             </set>
        </class>
    </hibernate-mapping> 
    2.3 主配置文件
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
    <!-- 4(数据库信息)+1(数据库方言)+2(生成sql格式化并打印)+1(数据库表生成策略)+1(加载映射文件)+
    1(事务隔离级别)+1(配置current_session_context) -->    
    <hibernate-configuration>
    <session-factory>
      <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
      <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/1715_hibernate05</property>
      <property name="hibernate.connection.username">root</property>
      <property name="hibernate.connection.password">123456</property>
      
     <!-- JBoss Tools 提示工具 -->
      <property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
      
      <property name="hibernate.show_sql">true</property>
      <property name="hibernate.format_sql">true</property>
      
      <property name="hibernate.hbm2ddl.auto">update</property>
        <!-- 隔离级别 -->
      <property name="hibernate.connection.isolation">4</property>
             
      <!-- 目的:要使用getCurrentSession()获取当前线程绑定的Session,必须要做如下配置:-->
      <property name="hibernate.current_session_context_class">thread</property>
      
      <mapping resource="com/qf/domain/Customer.hbm.xml"/>
      <mapping resource="com/qf/domain/Contact.hbm.xml"/>
    </session-factory>
    
    </hibernate-configuration>
    多对多:
    
    示例1:多个学生可以被多个老师教,多个老师可以教多个 学生;
    
    示例2:多个用户可以有多个角色,多个角色可以有多个用户。
    
                例如:马云既是老板又是演员。李彦宏既是企业家又是老板。
    
    1.User.java
    
        public class User {
            private Integer user_id;
            private String user_name;
            private String user_pwd;
            private String user_state;//用户状态
            
            //表达User和Role的多对多的关系
            private Set<Role> roles =new HashSet<>();
             set/get.......
        }
    
    2.Role.java
    
        public class Role {
            private Integer role_id;//角色编号
            private String role_name;//角色名
            private String role_memo;//角色备注
            
            //表达Role和User的多对多的关系
            private Set<User> users =new HashSet<>();
            set/get.......
        }
    
    3.User.hbm.xml
    
        <?xml version="1.0" encoding="UTF-8"?>
        <!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.qf.domain">
         <class name="User" table="user">
           <id name="user_id">
              <generator class="native"></generator>
           </id>
           <property name="user_name"></property>
           <property name="user_pwd"></property>
           <property name="user_state"></property>
           
           <!-- 表达多对多的关系  table:表示中间表的名称 
              inverse:true  不维护关系(放弃维护关系)
                      false:默认false,维护关系
              -->
           <set name="roles" table="user_role" inverse="true" >
              <!--  引用已经存在的键连接当前表User-->
              <key column="user_id1"></key>
             <!-- class:与当前表要建立关系的实体类名称
                  column:声明外键.表示在中间表中生成一个新的列。
                                         作为外键去连接与当前表要建立关系的表
                  -->
             <many-to-many class="Role" column="role_id1"></many-to-many>
           </set>
         </class>
         
         </hibernate-mapping>  
    
    4.Role.hbm.xml
    
        <?xml version="1.0" encoding="UTF-8"?>
        <!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.qf.domain">
         <class name="Role" table="role">
           <id name="role_id">
              <generator class="native"></generator>
           </id>
           <property name="role_name"></property>
           <property name="role_memo"></property>
           
           <!-- 表达多对多的关系  table:表示中间表的名称 -->
           <set name="users" table="user_role"  >
              <!--  引用已经存在的键连接当前表Role-->
              <key column="role_id1"></key>
             <!-- class:与当前表要建立关系的实体类名称
                  column:声明外键.表示在中间表中生成一个新的列。
                                         作为外键去连接与当前表要建立关系的表
                  -->
             <many-to-many class="User" column="user_id1"></many-to-many>
           </set>
         </class>
         
         </hibernate-mapping>  
    
    5.hibernate.cfg.xml
    
        <?xml version="1.0" encoding="UTF-8"?>
        <!DOCTYPE hibernate-configuration PUBLIC
            "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
            "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
        <!-- 4(数据库信息)+1(数据库方言)+2(生成sql格式化并打印)+1(数据库表生成策略)+1(加载映射文件)+
        1(事务隔离级别)+1(配置current_session_context) -->    
        <hibernate-configuration>
        <session-factory>
          <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
          <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/1715_hibernate06</property>
          <property name="hibernate.connection.username">root</property>
          <property name="hibernate.connection.password">123456</property>
          
         <!-- JBoss Tools 提示工具 -->
          <property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
          
          <property name="hibernate.show_sql">true</property>
          <property name="hibernate.format_sql">true</property>
          
          <property name="hibernate.hbm2ddl.auto">update</property>
            <!-- 隔离级别 -->
          <property name="hibernate.connection.isolation">4</property>
                 
          <!-- 目的:要使用getCurrentSession()获取当前线程绑定的Session,必须要做如下配置:-->
          <property name="hibernate.current_session_context_class">thread</property>
          
          <mapping resource="com/qf/domain/User.hbm.xml"/>
          <mapping resource="com/qf/domain/Role.hbm.xml"/>
        </session-factory>
        
        </hibernate-configuration>
    
    6.测试
    
           //插入
            @Test
            public void test01() {
                Session session =  HibernateUtils.getCurrentSession();
                Transaction transaction = session.beginTransaction();
                try {
                    User user1 =new User();
                    user1.setUser_name("马云11111");
                    
                    User user2 =new User();
                    user2.setUser_name("李彦宏1111");
                            
                    Role role1 =new Role();
                    role1.setRole_name("企业家11111");
                    
                    
                    Role role2 =new Role();
                    role2.setRole_name("演员11111");    
                    
                    //表达多对多的关系    
                    //从user角度出发表达关系
                    user1.getRoles().add(role1);
                    user1.getRoles().add(role2);
                    
                    user2.getRoles().add(role1);
                    user2.getRoles().add(role2);
                    
                    
                    //从role角度出发表达关系
                    role1.getUsers().add(user1);
                    role1.getUsers().add(user2);
                    
                    role2.getUsers().add(user1);
                    role2.getUsers().add(user2);
                    
                    
                    session.save(user1);
                    session.save(user2);
                            
                    session.save(role1);
                    session.save(role2);
                    
                    transaction.commit();
                } catch (Exception e) {
                    // TODO: handle exception
                    if (transaction!=null) {
                        transaction.rollback();
                    }
                }
            }
        执行以上代码报错:约束异常。
          解决方式一:去除掉一方关系表达维护,例如:删除掉30-34行代码
          解决方式二:代码不用改变,在不需要维护关系的地方添加inverse="true"(谁放弃给谁加)
                    示例:User维护User和Role的关系。    Role放弃关系维护。
              <set name="roles" table="user_role" inverse="true" >
              <!--  引用已经存在的键连接当前表User-->
              <key column="user_id1"></key>
             <!-- class:与当前表要建立关系的实体类名称
                  column:声明外键.表示在中间表中生成一个新的列。
                                         作为外键去连接与当前表要建立关系的表
                  -->
             <many-to-many class="Role" column="role_id1"></many-to-many>
             </set>       
                    
          备注:inverse
                       true:放弃维护关系
                       false:维护关系  ,默认        
    
    7.cascade级联操作(多表关系)
    
        /* cascade:级联操作   
         *       save-update(重点): 级联更新 .持久化当前对象的同时要持久化与之相关联的对象。
         *                   示例:session.save(User)  含义:持久化User的同时在持久化与User关联的类Role
                       在以上案例中可以去除40行和41行
         *       delete: 级联删除    删除一个对象的同时会删除掉与之相关连的对象  (不建议使用,慎重使用)    
         *       all:  save-update和delete结合一起
         */
              //删除用户(使用cascade="delete"会删除调用当前数据和与之关联的所有数据)
                @Test
                public void test02() {
                    Session session =  HibernateUtils.getCurrentSession();
                    Transaction transaction = session.beginTransaction();
                    try {
                         //删除一个用户
                        User user = session.get(User.class, 3);
                        session.delete(user);//删除user的同时删除了该user关联的role角色
                
                        transaction.commit();
                    } catch (Exception e) {
                        // TODO: handle exception
                        if (transaction!=null) {
                            transaction.rollback();
                        }
                    }
                }
                
                //给用户删除指定角色(不使用cascade="delete"删除)
                @Test
                public void test03() {
                    Session session =  HibernateUtils.getCurrentSession();
                    Transaction transaction = session.beginTransaction();
                    try {
                         //一个用户
                        User user = session.get(User.class, 5);
                        //给该用户删除一个角色
                        Role role= session.get(Role.class, 6);                
                         //从用户移除角色
                        user.getRoles().remove(role);//内连接查询            
                        session.delete(role);    
                        transaction.commit();
                    } catch (Exception e) {
                        // TODO: handle exception
                        if (transaction!=null) {
                            transaction.rollback();
                        }
                    }
                }
  • 相关阅读:
    7,C++ public, protected, private 继承的区别
    6,又一道经典的微软题
    5,一道经典的微软程序题
    33. Search in Rotated Sorted Array
    198,House Robber
    4,二维数组中指针的问题
    剑指offer——stack与queue的互相实现
    3,C语言文件读写
    2,虚函数
    剑指offer——已知二叉树的先序和中序排列,重构二叉树
  • 原文地址:https://www.cnblogs.com/a77355699/p/7905935.html
Copyright © 2011-2022 走看看