Hibernate_Day03

1、数据库表与表的关系

  • 一对一(了解)
    • 一个身份证号对应一个人,一个人只能有一个身份证号
      • 建表原则:唯一外键对应(一方外键对应一方主键)或者主键对应
  • 一对多
    • 一个部门对应多个员工,一个员工只能属于一个部门
      • 建表原则:在多的一方创建“外键”指向一的一方的主键
  • 多对多
    • 一门课程对应多个学生,一个学生对应多门课程
      • 建表原则:创建一个“中间表”,中间表至少有两个字段,分别作为“外键”指向多对多双方的“主键”

2、hibernate一对多的配置

  • 创建数据库和表

    • 自行建数据库
  • 建表

    CREATE TABLE `cst_customer` (
                                    `cust_id` bigint(32) NOT NULL AUTO_INCREMENT COMMENT '客户编号(主键)',
                                    `cust_name` varchar(32) NOT NULL COMMENT '客户名称(公司名称)',
                                    `cust_phone` varchar(64) DEFAULT NULL COMMENT '固定电话',
                                    PRIMARY KEY (`cust_id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
    
    CREATE TABLE `cst_linkmain` (
                                   `lkm_id` bigint(32) NOT NULL AUTO_INCREMENT COMMENT '联系人编号(主键)',
                                   `lkm_name` varchar(16) DEFAULT NULL COMMENT '联系人姓名',
                                   `lkm_cust_id` bigint(32) DEFAULT NULL COMMENT '客户id(外键)',
                                   PRIMARY KEY (`lkm_id`),
                                   KEY `FK_cst_linkman_lkm_cust_id` (`lkm_cust_id`),
                                   CONSTRAINT `FK_cst_linkman_lkm_cust_id` FOREIGN KEY (`lkm_cust_id`) REFERENCES `cst_customer` (`cust_id`) ON DELETE NO ACTION ON UPDATE NO ACTION
    ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
    
  • 分别创建实体类

    要点:在多的一方的写实体类的时候不写外键属性,要创建一的一方的对象并生成相应的set/get方法 ;在一的一方创建多的一方的集合并初始化,并生成相应的ser/get方法。hibernate默认的集合石set,也可以使用list。
    • 一的一方
      package com.chun.domain;
      
      import java.util.HashSet;
      import java.util.Set;
      
      /*
       * 客户的实体类*/
      public class Customer {
      private Long cust_id;
      private String cust_name;
      private String cust_phone;
      private Set<LinkMain> linkMains = new HashSet<>();
      
      public Set<LinkMain> getLinkMains() {
        return linkMains;
      }
      
      public void setLinkMains(Set<LinkMain> linkMains) {
          this.linkMains = linkMains;
      }
      
      public Long getCust_id() {
         return cust_id;
      }
      
      public void setCust_id(Long cust_id) {
         this.cust_id = cust_id;
      }
      
      public String getCust_name() {
         return cust_name;
      }
      
      public void setCust_name(String cust_name) {
         this.cust_name = cust_name;
      }
      
      public String getCust_phone() {
         return cust_phone;
      }
      
      public void setCust_phone(String cust_phone) {
         this.cust_phone = cust_phone;
      }
      
      @Override
      public String toString() {
         final String s = cust_id + " " + cust_name + " " + cust_phone;
         return s;
      }
      
      }
      
      
      • 多的一方
      package com.chun.domain;
      
      /*
       * 联系人实体类*/
      public class LinkMain {
      private Long lkm_id;
      private String lkm_name;
      //通过ORM表示一个联系人只可以属于一个客户
      //放置的一的一方的对像
      private Customer customer;
      
      public Customer getCustomer() {
         return customer;
      }
      
      public void setCustomer(Customer customer) {
         this.customer = customer;
      }
      
      public Long getLkm_id() {
         return lkm_id;
      }
      
      public void setLkm_id(Long lkm_id) {
         this.lkm_id = lkm_id;
      }
      
      public String getLkm_name() {
         return lkm_name;
      }
      
      public void setLkm_name(String lkm_name) {
         this.lkm_name = lkm_name;
      }
      //private String lkm_cust_id;
      }
      
      
    • 分别创建实体类的映射文件

      • 多的一方的映射文件
      <!DOCTYPE hibernate-mapping PUBLIC
       	   "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
           "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
      <hibernate-mapping>
        <class name="com.chun.domain.LinkMain" table="cst_linkmain">
           <id name="lkm_id" column="lkm_id">
      	        <generator class="native"></generator>
      	    </id>
      	    <property name="lkm_name" column="lkm_name"></property>
      	    <!--        配置多对一的属性:放置的是一的一方的对象-->
      	    <!--        many to one-->
      	    <!--        name:   一的一方的对象的属性名称-->
      	    <!--        class:一的一方对象的全路径-->
      	    <!--        column:多的一方的表的外键的名称-->
      	    <many-to-one name="customer" class="com.chun.domain.Customer" column="lkm_cust_id">
      	    </many-to-one>
      	</class>
      </hibernate-mapping>
      
      • 一的一方的映射文件
      <!DOCTYPE hibernate-mapping PUBLIC
              "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
              "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
      <hibernate-mapping>
          <class name="com.chun.domain.Customer" table="cst_customer">
              <!--        建立主键与OID映射-->
              <id name="cust_id" column="cust_id">
                  <generator class="native"></generator>
              </id>
          <property name="cust_phone" column="cust_phone"></property>
              <property name="cust_name" column="cust_name"></property>
              <!--        配置一对多的映射:放置多的一方的集合-->
              <!--        set标签-->
              <!--        name:多的一方的集合的名称-->
              <set name="linkMains">
                  <!--            key标签-->
                  <!--            column:多的一方的外键   -->
                  <key column="lkm_cust_id"></key>
                  <!--            one-to-many标签-->
                  <!--            class::多的一方的类的全路径-->
                  <one-to-many class="com.chun.domain.LinkMain"></one-to-many>
              </set>
          </class>
      </hibernate-mapping>
      
  • 配置hibernate.cfg.xml核心配置文件

    <?xml version='1.0' encoding='utf-8'?>
    <!--在hibernate-core-5.0.7.Final.jar/org.hibernate/hibernate-configuration-3.0.dtd引入约束-->
    <!DOCTYPE hibernate-configuration PUBLIC
            "-//Hibernate/Hibernate Configuration DTD//EN"
            "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
    <hibernate-configuration>
        <session-factory>
            <!--        在session-factory中配置基本必需的数据库连接-->
            <!--        数据库驱动配置-->
            <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
            <!--        要连接的数据库-->
            <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernatedaythree?useUnicode=true&amp;characterEncoding=UTF8</property>
            <!--        用户名-->
            <property name="hibernate.connection.username">root</property>
            <!--        用户密码-->
            <property name="hibernate.connection.password">980828</property>
            <!--        配置hibernate的方言-->
            <property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
            <!--        可选配置-->
            <!--        Mysql语句打印配置-->
            <property name="hibernate.show_sql ">true</property>
            <!--        格式化Mysql语句-->
            <property name="hibernate.format_sql">true</property>
            <property name="hibernate.hbm2ddl.auto">update</property>
            <!--        &配置C3P0连接池-->
            <property name="connection.provider_class">org.hibernate.c3p0.internal.C3P0ConnectionProvider</property>
            <!--在连接池中可用的数据库连接的最少数目 -->
            <property name="c3p0.min_size">5</property>
            <!--在连接池中所有数据库连接的最大数目  -->
            <property name="c3p0.max_size">20</property>
            <!--设定数据库连接的过期时间,以秒为单位,
            如果连接池中的某个数据库连接处于空闲状态的时间超过了timeout时间,就会从连接池中清除 -->
            <property name="c3p0.timeout">120</property>
            <!--3000秒检查所有连接池中的空闲连接 以秒为单位-->
            <property name="c3p0.idle_test_period">3000</property>
            <!--        引入映射文件-->
            <mapping resource="com/chun/domain/Customer.hbm.xml"></mapping>
            <mapping resource="com/chun/domain/LinkMain.hbm.xml"></mapping>
        </session-factory>
    </hibernate-configuration>
    
  • 引入工具类

    package com.chun.Utils;
    
    
    import org.hibernate.Session;
    import org.hibernate.SessionFactory;
    import org.hibernate.cfg.Configuration;
    
    public class HibernateUtils {
        private static final Configuration configuration;
        private static final SessionFactory sessionFactory;
    
        static {
            configuration = new Configuration().configure();
            sessionFactory = configuration.buildSessionFactory();
        }
    
        public static Session openSession() {
            return sessionFactory.openSession();
        }
    
        public static Session getCurrentSession() {
            return sessionFactory.getCurrentSession();//需要配置,因为默认没有开启
        }
    
    }
    
    
  • 编写测试类(只保存一边是不可以的,需要通过级联配置才可以,分别是级联保存或更新、级联删除)


    运行结果
    在这里插入图片描述

3、hibernate的级联操作

  • 什么是级联

    • 操作一个对象的时候,会同时操作其关联的对象
  • 级联具有方向性

    • 操作一的一方,是否操作到多的一方
    • 操作多的一方,是否操作到一的一方
  • 级联保存或更新

    • 保存客户级联联系人
      • 看操作的主体是谁,就在谁的配置文件中的另一方对象进行配置
        在这里插入图片描述
        在这里插入图片描述
        在这里插入图片描述
    • 保存联系人级联客户
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
  • 级联删除,删除一边的时候,另一边的也删除了

    • 看操作的主主体是谁,就在谁的配置文件进行配置
      • 删除客户级联联系人
        在这里插入图片描述
        在这里插入图片描述
        在这里插入图片描述
        在这里插入图片描述
    • 删除联系人删除客户
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
    • 一对多设置了双向关联,会产生多余的Sql语句(因为两边都可以维护外键)

      • 查看客户和联系人的配置文件中,会发现都有有一个外键
      • 解决多余的SQL语句
        • 单向维护:有些地方不可以的
        • 使一方放弃外键维护权:一的一方放弃
          • 在一的一方的配置中在set的集合进行配置 -inverse=“true”
            在这里插入图片描述
      • 区分cascade、inverse
        • cascade是关联级联操作,inverse是放弃外键

4、hibernate多对多的配置

  • 创建数据库和表

    • 自行建数据库
  • 建表

    	CREATE TABLE `sys_user` (
      `user_id` bigint(32) NOT NULL AUTO_INCREMENT COMMENT '用户id',
      `user_name` varchar(64)  NULL COMMENT '用户名称',
      `user_password` varchar(32)  NULL COMMENT '用户密码',
      PRIMARY KEY (`user_id`)
    	) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
    
    CREATE TABLE `sys_role` (
    `role_id` bigint(32) NOT NULL AUTO_INCREMENT,
    `role_name` varchar(32)  NULL COMMENT '角色名称',
    `role_memo` varchar(128) DEFAULT NULL COMMENT '备注',
    PRIMARY KEY (`role_id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
    

    中间表

    CREATE TABLE `sys_user_role` (
    `role_id` bigint(32) NOT NULL COMMENT '角色id',
    `user_id` bigint(32) NOT NULL COMMENT '用户id',
    PRIMARY KEY (`role_id`,`user_id`),
    KEY `FK_user_role_user_id` (`user_id`),
    CONSTRAINT `FK_user_role_role_id` FOREIGN KEY (`role_id`) REFERENCES `sys_role` (`role_id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
    CONSTRAINT `FK_user_role_user_id` FOREIGN KEY (`user_id`) REFERENCES `sys_user` (`user_id`) ON 	DELETE NO ACTION ON UPDATE NO ACTION
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
  • 分别创建实体类

    import java.util.HashSet;
    import java.util.Set;
    
    public class User {
    
        private long userId;
        private String userName;
        private String userPassword;
        private Set<Role> roles = new HashSet<>();
    
        public Set<Role> getRoles() {
            return roles;
        }
    
        public void setRoles(Set<Role> roles) {
            this.roles = roles;
        }
    
        public long getUserId() {
            return userId;
        }
    
        public void setUserId(long userId) {
            this.userId = userId;
        }
    
    
        public String getUserName() {
            return userName;
        }
    
        public void setUserName(String userName) {
            this.userName = userName;
        }
    
    
        public String getUserPassword() {
            return userPassword;
        }
    
        public void setUserPassword(String userPassword) {
            this.userPassword = userPassword;
        }
    
    }
    
    
    
    import java.util.HashSet;
    import java.util.Set;
    
    public class Role {
    
      private long roleId;
      private String roleName;
      private String roleMemo;
      private Set<User> users = new HashSet<>();
    
      public Set<User> getUsers() {
        return users;
      }
    
      public void setUsers(Set<User> users) {
        this.users = users;
      }
    
      public long getRoleId() {
        return roleId;
      }
    
      public void setRoleId(long roleId) {
        this.roleId = roleId;
      }
    
    
      public String getRoleName() {
        return roleName;
      }
    
      public void setRoleName(String roleName) {
        this.roleName = roleName;
      }
    
    
      public String getRoleMemo() {
        return roleMemo;
      }
    
      public void setRoleMemo(String roleMemo) {
        this.roleMemo = roleMemo;
      }
    
    }
    
    
  • 分别创建实体类的映射文件 (在多对多的情况下一定要使一方放弃外键,一般是被选择的一方放弃外键)

    <?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>
    
        <class name="com.chun.domain.Role" table="sys_role" schema="hibernatedaythree">
            <id name="roleId" column="role_id">
                <generator class="native"></generator>
            </id>
            <property name="roleName" column="role_name"/>
            <property name="roleMemo" column="role_memo"/>
            <set name="users" table="sys_user_role" inverse="true">
                <key column="role_id"></key>
                <many-to-many class="com.chun.domain.User" column="user_id"></many-to-many>
            </set>
        </class>
    </hibernate-mapping>
    
    <?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>
    
        <class name="com.chun.domain.User" table="sys_user" schema="hibernatedaythree">
            <id name="userId" column="user_id">
                <generator class="native"></generator>
            </id>
            <property name="userName" column="user_name"/>
            <property name="userPassword" column="user_password"/>
            <!--        name:多方的集合属性-->
            <!--        table:中间表-->
            <set name="roles" table="sys_user_role">
                <!--            column:当前的对象对应中间表的外键-->
                <key column="user_id"></key>
                <!--            many-to-many-->
                <!--            class:对方的类的全路径-->
                <!--            column:对方的主键在中间表的外键-->
                <many-to-many class="com.chun.domain.Role" column="role_id"></many-to-many>
            </set>
        </class>
    </hibernate-mapping>
    

    一定要注意插入数据库时的编码格式

  • 配置hibernate.cfg.xml核心配置文件

    <?xml version='1.0' encoding='utf-8'?>
    <!--在hibernate-core-5.0.7.Final.jar/org.hibernate/hibernate-configuration-3.0.dtd引入约束-->
    <!DOCTYPE hibernate-configuration PUBLIC
            "-//Hibernate/Hibernate Configuration DTD//EN"
            "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
    <hibernate-configuration>
        <session-factory>
            <!--        在session-factory中配置基本必需的数据库连接-->
            <!--        数据库驱动配置-->
            <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
            <!--        要连接的数据库-->
            <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernatedaythree?useUnicode=true&amp;characterEncoding=UTF8</property>
            <!--        用户名-->
            <property name="hibernate.connection.username">root</property>
            <!--        用户密码-->
            <property name="hibernate.connection.password">980828</property>
            <!--        配置hibernate的方言-->
            <property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
            <!--        可选配置-->
            <!--        Mysql语句打印配置-->
            <property name="hibernate.show_sql ">true</property>
            <!--        格式化Mysql语句-->
            <property name="hibernate.format_sql">true</property>
            <property name="hibernate.hbm2ddl.auto">update</property>
            <!--        &配置C3P0连接池-->
            <property name="connection.provider_class">org.hibernate.c3p0.internal.C3P0ConnectionProvider</property>
            <!--在连接池中可用的数据库连接的最少数目 -->
            <property name="c3p0.min_size">5</property>
            <!--在连接池中所有数据库连接的最大数目  -->
            <property name="c3p0.max_size">20</property>
            <!--设定数据库连接的过期时间,以秒为单位,
            如果连接池中的某个数据库连接处于空闲状态的时间超过了timeout时间,就会从连接池中清除 -->
            <property name="c3p0.timeout">120</property>
            <!--3000秒检查所有连接池中的空闲连接 以秒为单位-->
            <property name="c3p0.idle_test_period">3000</property>
            <!--        设置事务隔离级别-->
            <property name="hibernate.connection.isolation">4</property>
            <!--        配置Session绑定当前对象-->
            <property name="hibernate.current_session_context_class">thread</property>
            <!--        引入映射文件-->
            <mapping resource="com/chun/domain/Customer.hbm.xml"></mapping>
            <mapping resource="com/chun/domain/LinkMain.hbm.xml"></mapping>
            <mapping resource="com/chun/domain/Role.hbm.xml"/>
            <mapping resource="com/chun/domain/User.hbm.xml"/>
        </session-factory>
    </hibernate-configuration>
    
  • 编写测试类(只保存一边是不可以的,需要通过级联配置才可以,分别是级联保存或更新、级联删除)

    在这里插入图片描述
    在这里插入图片描述
    级联保存或更新–保存客户级联保存角色(被保存的是角色),谁操作在谁的配置文件进行配置,并且外键由谁操作谁维护
    在这里插入图片描述
    在这里插入图片描述
    级联删除–删除客户级联删除角色(顺带着被删除的是角色),谁操作在谁的配置文件进行配置,并且外键由谁操作谁维护
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值