Hibernate_day3笔记

1、回顾

1.1 Hibernate的持久化类的编写规则

  • 无参构造
  • 属性私有
  • 属性尽量使用包装类
  • 提供一个唯一的OID与其对应
  • 不要使用final修饰

1.2 Hibernate的主键生成策略

  • 主要分类
    • 自然主键
    • 代理主键
  • 主键生成策略
    • increment
    • identity
    • sequence
    • UUID
    • native
    • assigned
    • foreign

1.3 Hibernate的持久化类的三种装态

  • 三种状态
    • 瞬时态:没有唯一标识OID,也没有被Session管理
    • 持久态:有唯一标识OID,且被Session管理
    • 脱管态:有唯一的标识OID,但没有被Session管理
  • 状态转换

1.4 Hibernate的一级缓存

  • 一级缓存:Hibernate优化手段,成为Session级别的缓存,是自带的,不可卸载的
  • 一级缓存:快照区

1.5 Hibernate的事务管理

  • 事务的回顾
    • 事务的概念:
    • 事务的特性:
    • 引发安全性问题:
    • 安全性问题解决:
  • HIbernate解决读问题
    • 配置设置隔离级别
  • Hibernate解决Service事务
    • 采用的是线程绑定的方式:getCurrentSession()

1.6 Hibernate的其他API

  • Query: ;HQL面向对象的方式查询
  • Criteria: ;QBC完成面向对象化
  • SQLQuery: ;SQL查询

2、Hibernate一对多关联映射

2.1 一对多关系

  • 什么样关系属于一对多?
    • 一个部门对对于多个员工,一个员工只能属于某一个部门。
    • 一个客户对应多个联系人,一个联系人只能属于某一个客户。
  • 一对多的建表原则
    • 在多的一方 创建外键,指向一的一方的主键

2.2 多对多关系

  • 什么样的关系属于多对多?
    • 一个学生可以选择对门课程,一门课程也可以被多个学生选择。
    • 一个订单下可以有不同的商品,一个商品也可以在不同的订单里面。
    • 一个用户可以选择多个角色,一个角色也可以被多个用户选择。
  • 多对多的建表原则
    • 创建一个中间表,中间表至少有两个字段,分别作为外键指向多对多双方的主键。

2.3 一对一关系(了解)

  • 什么样的额关系属于一对第一?
  • 一个公司只能有一个注册地址,一个注册地址也只能被一个公司注册。
  • 一对一的建表原则
    • 方式一:唯一外键对应
    • 方式二:主键对应

2.4 Hibernate一对多的配置关系

  • 创建数据库和表

        CREATE TABLE `cst_customer` (
      `cust_id` BIGINT(32) NOT NULL AUTO_INCREMENT COMMENT '客户编号(主键)',
      `cust_name` VARCHAR(32) NOT NULL COMMENT '客户名称(公司名称)',
      `cust_source` VARCHAR(32) DEFAULT NULL COMMENT '客户信息来源',
      `cust_industry` VARCHAR(32) DEFAULT NULL COMMENT '客户所属行业',
      `cust_level` VARCHAR(32) DEFAULT NULL COMMENT '客户级别',
      `cust_phone` VARCHAR(64) DEFAULT NULL COMMENT '固定电话',
      `cust_mobile` VARCHAR(16) DEFAULT NULL COMMENT '移动电话',
      PRIMARY KEY (`cust_id`)
    ) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
    
    ---------------------------------------------------------------------
    
    CREATE TABLE `cst_linkman` (
      `lkm_id` BIGINT(32) NOT NULL AUTO_INCREMENT COMMENT '联系人编号(主键)',
      `lkm_name` VARCHAR(16) DEFAULT NULL COMMENT '联系人姓名',
      `lkm_cust_id` BIGINT(32) NOT NULL COMMENT '客户id',
      `lkm_gender` CHAR(1) DEFAULT NULL COMMENT '联系人性别',
      `lkm_phone` VARCHAR(16) DEFAULT NULL COMMENT '联系人办公电话',
      `lkm_mobile` VARCHAR(16) DEFAULT NULL COMMENT '联系人手机',
      `lkm_email` VARCHAR(64) DEFAULT NULL COMMENT '联系人邮箱',
      `lkm_qq` VARCHAR(16) DEFAULT NULL COMMENT '联系人qq',
      `lkm_position` VARCHAR(16) DEFAULT NULL COMMENT '联系人职位',
      `lkm_memo` VARCHAR(512) DEFAULT NULL COMMENT '联系人备注',
      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=3 DEFAULT CHARSET=utf8;
    
  • 创建实体

    public class LinkMan {
    private Long lkm_id;
    private String lkm_name;
    private String lkm_gender;
    private String lkm_phone;
    private String lkm_mobile;
    private String lkm_email;
    private String lkm_qq;
    private String lkm_position;
    private String lkm_memo;
    
    //通过ORM方式表示:一个联系人只能属于一个客户
    //放置的是一的一方的对象。
    private Customer customer;
    
    -----------------------------------------------------
    
    public class Customer {
    private Long cust_id;
    private String cust_name;
    private String cust_source;
    private String cust_industry;
    private String cust_level;
    private String cust_phone;
    private String cust_mobile;
    
    
    //通过ORM方式表示:一个客户对应多个联系人
    //放置多的一方的集合:Hibernate默认用的是Set集合
    private Set<LinkMan> linkMans = new HashSet<LinkMan>(); 
    
  • 创建映射

    • linkMan.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>
          <class name="com.hibernate.demo01.LinkMan" table="cst_linkman">
              <id name="lkm_id" column="lkm_id">
                  <generator class="native"></generator>
              </id>
              <property name="lkm_name" column="lkm_name"></property>
              <property name="lkm_gender" column="lkm_gender"></property>
              <property name="lkm_phone" column="lkm_phone"></property>
              <property name="lkm_mobile" column="lkm_mobile"></property>
              <property name="lkm_email" column="lkm_email"></property>
              <property name="lkm_qq" column="lkm_qq"></property>
              <property name="lkm_position" column="lkm_position"></property>
              <property name="lkm_memo" column="lkm_memo"></property>
      
              <!-- 配置多对一的关系 :放置的是一 的一方的对象-->
              <!-- 
                  many-to-one 标签:
                      * name   :一的一方的对象的属性名 
                      * class  :一的一方的类的全路径
                      * column :在多的一方的外键的名称
               -->
              <many-to-one name="customer" class="com.hibernate.demo01.Customer" column="lkm_cust_id"></many-to-one>
      
          </class>
      </hibernate-mapping>
      
    • Customer.hb,.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>
          <!-- 建立类与表的映射 -->
          <class name="com.hibernate.day02.Customer" table="cst_customer">
              <!-- 建立类中的属性与表中的主键对应 -->
              <id name="cust_id" column="cust_id">
                      <!-- 主键生成策略 -->
                  <generator class="native"></generator>
              </id>
              <!-- 建立类中的普通的属性和表的字段的对应 -->
              <property name="cust_name" column="cust_name"></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_phone" column="cust_phone"></property>
              <property name="cust_mobile" column="cust_mobile"></property>
      
              <!--配置一对多的映射:放置的是多的一方的对象的集合  -->
              <!-- 
                  set标签:
                      * name   :多的一方的对象集合的属性名称
               -->
              <set name="linkMans">
                  <!-- 
                      key标签:
                          * column:多的一方的外键的名称
                   -->
                  <key column="lkm_cust_id"></key>
                  <!-- 
                      one=to-many:标签
                          * class: 多的一方的类的全路径
                   -->
                  <one-to-many class="com.hibernate.domain.LinkMan"/>
              </set>
          </class>
      </hibernate-mapping>
      
  • 创建核心配置文件

    <!-- 引入映射-->
    <mapping resource="com/hibernate/domain/Customer.hbm.xml"/>
    <mapping resource="com/hibernate/domain/LinkMan.hbm.xml"/>
    
  • 一对多的关系只保存一边是否可以?(不可以)

    public void Test02() {
        Session session = HibernateUtils.openSession();
        Transaction transaction = session.beginTransaction();
    
        Customer customer = new Customer();
        customer.setCust_name("Jackson");
    
        LinkMan linkMan = new LinkMan();
        linkMan.setLkm_name("Tony");
    
        customer.getLinkMans().add(linkMan);
    
        //只保存一边是否可以:不可以,报一个瞬时对象异常。持久态对象关联了一个瞬时态对象
        //session.save(customer);
        session.save(linkMan);
    
        transaction.commit();
    }
    

2.5 一对多的级联操作

  • 什么叫做级联:
    • 级联指的是,操作某一个对象的时候,是否会同时操作其关联的对象。
  • 级联是有方向性:
    • 操作一的一方的时候,是否操作的多的一方。
    • 操作多的一方的时候,是否会操作到一的一方。
  • 级联保存或更新:

    • 保存客户,级联联系人。
    • 保存联系人,级联客户。

      /**
       *  级联保存或更新
       *      * 保存客户级联联系人:操作的主体是客户对象,需要在Customer.hbm.xml中进行配置 
       *      * <set name="linkMans" cascade="save-update"> 
       *          * 添加cascade属性
       *      
       *      * 保存联系人级联客户:操作的主体是联系人,需要在LinkMan.hbm.xml中进行配置
       *      * <many-to-one name="customer" cascade="save-update" class="com.hibernate.domain.Customer" column="lkm_cust_id" />
       *          * 添加cascade属性
       */
      public void test03() {
          Session session = HibernateUtils.openSession();
          Transaction transaction  = session.beginTransaction();
      
          Customer customer = new Customer();
          customer.setCust_name("陈平");
      
          LinkMan linkMan = new LinkMan();
          linkMan.setLkm_name("江婉");
      
          customer.getLinkMans().add(linkMan);
          linkMan.setCustomer(customer);
      
          //session.save(customer);
          session.save(linkMan);
      
          transaction.commit();
      }
      
  • 级联删除:

    • 删除一边的时候,同时将另一方的数据也一并删除。

      @Test
      /**
       * 级联删除
       *      * 删除客户,级联删除联系人
       *      <set name="linkMans" cascade="save-update,delete"> 
       *      属性cascade中添加了delete
       */
      public void demo04() {
          Session session = HibernateUtils.openSession();
          Transaction transaction = session.beginTransaction();
      
          //没有设置级联删除,默认情况下,先将外键设置为null
          Customer customer = session.get(Customer.class, 1l);
          session.delete(customer);
      
          transaction.commit();
      }
      
  • 一对多设置了双向关联产生多余的SQL语句
    • 解决多余的SQL语句
      • 单向维护
      • 使一方放弃外键维护权
        • 一的一方放弃。在set上配置inverse为true。
      • 一对多的关联查询的修改的时候。

-

3 Hibernate的多对多关联映射

3.1 HIbernate多对多关系的配置

3.1.1 创建表

  • 用户表

    CREATE TABLE `sys_user` (
     `user_id` BIGINT(32) NOT NULL  AUTO_INCREMENT COMMENT '用户id',
    `user_code` VARCHAR(32) NOT NULL COMMENT '用户账号',
    `user_name` VARCHAR(64) NOT NULL COMMENT '用户名称',
     `user_password` VARCHAR(32) NOT NULL COMMENT '用户密码',
     `user_state` CHAR(1) NOT NULL COMMENT '1:正常,0:暂停',
      PRIMARY KEY (`user_id`)
    ) ENGINE=INNODB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8;
    
  • 角色表

    CREATE TABLE `sys_role` (
    `role_id` bigint(32) NOT NULL AUTO_INCREMENT,
    `role_name` varchar(32) NOT NULL COMMENT '角色名称',
    `role_memo` varchar(128) DEFAULT NULL COMMENT '备注',
    PRIMARY KEY (`role_id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=6 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;
    

3.1.2 创建实体类

  • 创建用户实体类User,生成set,get方法

    public class User {
    private Long user_id;
    private String user_code;
    private String user_name;
    private String user_password;
    private String user_state;
    
    //设置多对多关系:表示一个用户选择多个角色
    private Set<Role> roles = new HashSet<Role>();
    
  • 创建角色实体类Role,生成set,get方法

    public class Role {
    private Long role_id;
    private String role_name;
    private String role_memo;
    
    //一个角色被多个用户选择
    //放置的是用户的集合
    private Set<User> users = new HashSet<>();
    

3.1.4 创建映射

  • 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>
        <class name="com.hibernate.domain.User" table="sys_user">
            <id name="user_id" column="user_id">
                <generator class="native"></generator>
            </id>
            <property name="user_code" column="user_code"></property>
            <property name="user_name" column="user_name"></property>
            <property name="user_password" column="user_password"></property>
            <property name="user_state" column="user_state"></property>
    
            <!-- 建立与角色的多对多的映射关系 -->
            <!-- 
                * set 集合:
                    * name      :对方的集合的属性名称
                    * table     :多对多关系需要使用中间表,放的是中间表单的名称
             -->
            <set name="roles" table="sys_user_role">
                <!-- column : 当前对象对应的中间表的外键的名称-->
                <key column="user_id"></key>
    
                <!-- 
                    class       :对方类的全路径
                    colummn     :对方的对象在中间表的外键的名称
                 -->
                <many-to-many class="com.hibernate.domain.Role" column="role_id"/>
            </set>
    
        </class>
    </hibernate-mapping> 
    
  • 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>
        <class name="com.hibernate.domain.Role" table="sys_role">
            <id name="role_id" column="role_id">
                <generator class="native"></generator>
            </id>
            <property name="role_name" column="role_name"></property>
            <property name="role_memo" column="role_name"></property>
    
            <set name="users" table="sys_user_role">
                <key column="role_id"></key>
                <many-to-many class="com.hibernate.domain.User" column="user_id"/>
            </set>
        </class>
    </hibernate-mapping>
    

3.1.5创建测试类

@Test
/**
 * 保存多条记录:保存多个用户和角色
 */
public void demo02() {
    Session session = HibernateUtils.openSession();
    Transaction transaction = session.beginTransaction();

    //创建两个用户
    User user1 = new User();
    user1.setUser_name("赵子龙");
    User user2 = new User();
    user2.setUser_name("周瑜");

    //创建三个角色
    Role role1 = new Role();
    role1.setRole_name("研发部");
    Role role2= new Role();
    role2.setRole_name("市场部");
    Role role3 = new Role();
    role3.setRole_name("公关部");

    //设置双向的关联关系
    user1.getRoles().add(role1);
    user1.getRoles().add(role2);

    user2.getRoles().add(role2);
    user2.getRoles().add(role3);

    role1.getUsers().add(user1);
    role2.getUsers().add(user1);
    role2.getUsers().add(user2);
    role3.getUsers().add(user2);

    //保存操作:多对多建立了双向关系,必须有一方放弃外键保护。
    //一般被动方放弃外键维护权
    session.save(user1);
    session.save(user2);
    session.save(role1);
    session.save(role2);
    session.save(role3);

    transaction.commit();
}

3.2 Hibernate多对多的操作

  • 只保存一边是否可以?
    • 不可以,会报瞬时对象异常
  • 多对多的级联保存或更新
    • 在用户的映射文件中配置
  • 多对多的级联删除

4、多对多的其他操作

4.1 给用户选择角色

4.2 给用户改选角色

4.3 给用户删除角色

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值