多表关系映射


1、一对一(会用即可)

主表:没有外键 有主键

从表:拥有外键的是从表

先操作从表,再去操作主表

one-to-one  ,many-to-one 只是表达多个表之间的关系。

外键:目的是多表连接
主键:目的是唯一标识数据

示例: 一个人对应一个身份证 ,一夫一妻制, 一个萝卜一个坑。。。。

一对一的关系用程序如何描述:

示例:一夫一妻制

Husband.java

 
   
   
   
   
public class Husband{
   private Integer marryId; //结婚编号
   private String name; //名称
   private Integer age; //年龄
   private  Integer  hid; //丈夫的身份证号   
   private  Wife wife; //丈夫和妻子有一对一的关系 
   set/get....
}

Wife.java

 
   
   
   
   
public class Wife{
   private Integer marryId; //妻子的身份证号
   private String name; //名称
   private Integer age; //年龄
   private  Integer  wid; //结婚编号  
   private   Husband  husband;//妻子和丈夫有一对一的关系
   set/get....
}

1.1 方式一: 按照主键映射 (主键都是一样的)

用已有的主键充当外键去连接表来表示关系

元数据配置文件:

1.1.1 Husband.hbm.xml

 
   
   
   
   
 version="1.0" encoding="UTF-8"?>
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
 package="com.qf.domain">
     name="Husband" table="husband">
         name="marryId">
             class="native">
        
         name="name">
         name="age">
         name="hid">
      
       name="wife" constrained="true">
    

1.1.2 Wife.hbm.xml

 
   
   
   
   
 version="1.0" encoding="UTF-8"?>
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
     package="com.qf.domain">
     name="Wife" table="wife">
         name="marryId">
             class="native">
        
         name="name">
         name="age">
         name="wid">
      
        name="husband">
    

1.1.3 测试

 
   
   
   
   
/**
 * one-to-one表示一对一的关系。  
 * constrained="true"表示外键约束。当前类映射表的主键作为外键去连接另外一个表的主键。
 * 示例: husband的主键作为外键去连接wife的主键。建立了一对一的关系(夫妻关系)。
 * 
 * 主表 wife
 * 副表(从表) husband  维护外键,通过外键去连接主表的主键
 * 
 * 手动删除表的先删除副表。再删除主表。
 * 
 * 方式一: 按照主键关系映射的(用已有的主键充当外键去连接关系) 上午重点:
 * 方式二:按照外键关系映射的。(给表插入额外的一个列作为外键去连接另外一个表) 
 */
@Test
    public void test01() {
        Session session = HibernateUtils.getCurrentSession();
        Transaction transaction = session.beginTransaction();
        try {
            Husband husband =new Husband();
            husband.setName("丈夫");
            
            Wife wife =new Wife();
            wife.setName("妻子");
            
            //表达一对一的关系
            husband.setWife(wife);          
            wife.setHusband(husband);
            
            
            //有约束关系的表后插入(该表插入的时候要 找对应的关系的那条数据)
            //先插入主表
            session.save(wife);
            //后插入副表
            session.save(husband);  
            transaction.commit();
        } catch (Exception e) {
            // TODO: handle exception
            if (transaction!=null) {
                transaction.rollback();
            }
        }
    }

1.2 按照外键映射

给表额外插入一个列作为外键去连接另一个表

java持久化类

 
   
   
   
   
Wife.java
public class Wife{
   private Integer wid; //妻子的身份证号(主键)
   private String name; //名称
   private Integer age; //年龄
   private  Integer  marryId; //结婚编号  
   private   Husband  husband;//妻子和丈夫有一对一的关系
   set/get.... 
}
Husband.java
public class Husband{
   private Integer hid; //丈夫的身份证号 (主键) 
   private String name; //名称
   private Integer age; //年龄
   private  Integer  marryId; //结婚编号
   private  Wife wife; //丈夫和妻子有一对一的关系 
   set/get....
   
   //理解:  多个表中主键都有各自的含义及内容的时候(主键不一样)
   //给husband额外插入一个列wife_id1,作为外键去连接wife表
}

1.2.1 Husband.hbm.xml

 
   
   
   
   
 version="1.0" encoding="UTF-8"?>
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
 package="com.qf.domain">
     name="Husband" table="husband">
         name="hid">
             class="native">
        
         name="name">
         name="age">
         name="marryId">
      
       name="wife" unique="true" column="wife_id1">  
    

1.2.2 Wife.hbm.xml

 
   
   
   
   
 version="1.0" encoding="UTF-8"?>
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
     package="com.qf.domain">
     name="Wife" table="wife">
         name="wid">
             class="native">
        
         name="name">
         name="age">
         name="marryId">
      
        name="husband">
    

1.2.3 测试

 
   
   
   
   
@Test
    public void test01() {
        Session session = HibernateUtils.getCurrentSession();
        Transaction transaction = session.beginTransaction();
        try {
           Husband husband =new Husband();
            husband.setName("丈夫1");
            
            Wife wife =new Wife();
            wife.setName("妻子1");
            
            //表达一对一的关系
            husband.setWife(wife);          
            wife.setHusband(husband);
            
            
            //有约束关系的表后插入(该表插入的时候要 找对应的关系的那条数据)
            //先插入主表
            session.save(wife);
            //后插入副表
            session.save(husband);
            
            transaction.commit();
        } catch (Exception e) {
            // TODO: handle exception
            if (transaction!=null) {
                transaction.rollback();
            }
        }
    }
    

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;
import java.util.HashSet;
import java.util.Set;
//主表
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.....
}

2.2 映射文件

Contact.hbm.xml
 
   
   
   
   
 version="1.0" encoding="UTF-8"?>
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
 package="com.qf.domain">
     name="Contact" table="contact">
         name="contact_id">
             class="native">
        
         name="contact_name" >
         name="contact_gender" >
         name="contact_phone" >
         name="contact_mobile" >
         name="contact_email" >
         name="contact_qq" >
         name="contact_position" >
         name="contact_memo" >
        
        
         name="customer" column="contact_cust_id">    
    
    
Customer.hbm.xml
 
   
   
   
   
 version="1.0" encoding="UTF-8"?>
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
 package="com.qf.domain">
     name="Customer" table="customer">
         name="cust_id" column="cust_id">
             class="native">
        
         name="cust_name" column="cust_name">
         name="cust_user_id" column="cust_user_id">
         name="cust_create_id" column="cust_create_id">
         name="cust_source" column="cust_source">
         name="cust_industry" column="cust_industry">
         name="cust_level" column="cust_level">
         name="cust_linkman" column="cust_linkman">
         name="cust_phone" column="cust_phone">
         name="cust_mobile" column="cust_mobile">   
        
          name="contacts">
            
            column="contact_cust_id">
           
            class="Contact"/>
         
    
    

2.3 主配置文件

 
   
   
   
   
 version="1.0" encoding="UTF-8"?>
    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
  
   name="hibernate.connection.driver_class">com.mysql.jdbc.Driver
   name="hibernate.connection.url">jdbc:mysql://localhost:3306/1715_hibernate05
   name="hibernate.connection.username">root
   name="hibernate.connection.password">123456
  
 
   name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect
  
   name="hibernate.show_sql">true
   name="hibernate.format_sql">true
  
   name="hibernate.hbm2ddl.auto">update
    
   name="hibernate.connection.isolation">4
         
  
   name="hibernate.current_session_context_class">thread
  
  
   resource="com/qf/domain/Customer.hbm.xml"/>
   resource="com/qf/domain/Contact.hbm.xml"/>

2.4 测试

 
   
   
   
   
@Test
    public void test001() {
         Session session = HibernateUtils.getCurrentSession();
         Transaction transaction =  session.beginTransaction();
         try {
              //1个客户
             Customer customer= new Customer();
             customer.setCust_name("阿里巴巴");
             
             
             //多个联系人,示例2个
             Contact contact1 =new Contact();
             contact1.setContact_name("马云");
             Contact contact2 =new Contact();
             contact2.setContact_name("李总");
             
             //表达多表关系
             //一对多
             //把联系人给客户添加上
             customer.getContacts().add(contact1);
             customer.getContacts().add(contact2);
             
             //多对一
             contact1.setCustomer(customer);
             contact2.setCustomer(customer);
             
             
             //持久化保存
              session.save(customer);
              session.save(contact1);
              session.save(contact2);
             
             
             transaction.commit();
        } catch (Exception e) {
            // TODO: handle exception
            if (transaction!=null) {
                transaction.rollback();
            }
        }
    }
    
    
    //给指定客户添加新的联系
    
    //持久态的对象会自动更新,已经在数据库中
    //瞬时状态和游离状态必须通过方法转化成持久态才可以保存到数据
    @Test
    public void test002() {
         Session session = HibernateUtils.getCurrentSession();
         Transaction transaction =  session.beginTransaction();
         try {
             //1.先找出客户
             Customer customer = session.get(Customer.class, 1);
            
             //2.新加联系人
             Contact contact =new Contact();
             contact.setContact_name("刘总");
             
             //表达一对多的关系
             customer.getContacts().add(contact);
             
             //表达多对一的关系
             contact.setCustomer(customer);
             
             //保存
             session.save(contact);
             
             transaction.commit();
        } catch (Exception e) {
            // TODO: handle exception
            if (transaction!=null) {
                transaction.rollback();
            }
        }
    }

3、多对多(常见的,掌握)

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

 
   
   
   
   
 version="1.0" encoding="UTF-8"?>
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
  package="com.qf.domain">
  name="User" table="user">
    name="user_id">
       class="native">
   
    name="user_name">
    name="user_pwd">
    name="user_state">
   
   
    name="roles" table="user_role" inverse="true" >
      
       column="user_id1">
     
      class="Role" column="role_id1">
   
 
 
   

4.Role.hbm.xml

 
   
   
   
   
 version="1.0" encoding="UTF-8"?>
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
  package="com.qf.domain">
  name="Role" table="role">
    name="role_id">
       class="native">
   
    name="role_name">
    name="role_memo">
   
   
    name="users" table="user_role"  >
      
       column="role_id1">
     
      class="User" column="user_id1">
   
 
 
   

5.hibernate.cfg.xml

 
   
   
   
   
 version="1.0" encoding="UTF-8"?>
    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
  
   name="hibernate.connection.driver_class">com.mysql.jdbc.Driver
   name="hibernate.connection.url">jdbc:mysql://localhost:3306/1715_hibernate06
   name="hibernate.connection.username">root
   name="hibernate.connection.password">123456
  
 
   name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect
  
   name="hibernate.show_sql">true
   name="hibernate.format_sql">true
  
   name="hibernate.hbm2ddl.auto">update
    
   name="hibernate.connection.isolation">4
         
  
   name="hibernate.current_session_context_class">thread
  
   resource="com/qf/domain/User.hbm.xml"/>
   resource="com/qf/domain/Role.hbm.xml"/>

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" >
      
      <key column="user_id1">key>
     
     <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();
                }
            }
        }

8.练习

你可能感兴趣的:(mysql)