栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

重量级ORM框架--持久化框架Hibernate【关系映射详解】

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

重量级ORM框架--持久化框架Hibernate【关系映射详解】

hibernate

Hibernate是一款重量级的持久层框架,目前市面上的我很少见还有项目在开发时候使用他,之所以要学习这个,因为公司最近有一个系统升级的项目,之前的老系统用到了Hibernate。

同样还是老套路,学习一个新技术或者新知识,首先去他的官网看

【官网】:https://hibernate.org/orm/
【官方教程】:https://hibernate.org/orm/documentation/getting-started/
【github地址】:https://github.com/hibernate


目前hibernate已经更新到了6的版本,这里使用的5的版本

注意: Hibernate5.1;5.2官方推荐使用JDK1.8以及JDBC4

文章目录
  • hibernate
  • 一、generator主键策略
  • 二、对象关系映射:一对多映射
    • 2.1 测试准备
    • 2.2 创建实体
    • 2.3 hbm.xml文件修改
    • 2.4 编写测试类
  • 三、casecode和inverse配置
    • 3.1 CaseCade级联操作
    • 3.2 INVERSE反转配置
  • 四、对象关系映射:多对多映射
    • 4.1 多对多插入操作
      • 4.1.1 数据库设计
      • 4.1.2 对象设计
      • 4.1.3 映射的配置:fire::fire:
    • 4.2 多对多查询
    • 4.3 多对多级联添加操作
  • 五、对象关系映射:一对一映射
    • 5.1 数据库设计
    • 5.2 实体类设计
      • 5.2.1 外键关联
      • 5.2.2 主键关联
    • 5.3 配置文件
      • 5.3.1 外键关联
      • 5.3.2 主键关联
    • 5.4 测试
    • 5.4.1 外键关联
    • 5.4.2 主键关联


一、generator主键策略


generator配置:代表hibernate主键生成策略

【我们可以将其分为三大类】:

  1. 由数据库维护
    • identity:Mysql的auto_increment维护主键自增策略
    • sequence:Oracle使用sequence序列维护主键自增策略
    • native :本地策略,由hibernate自己根据数据库选择最优策略
  2. 由hibernate维护
    • uuid:生成32位16进制的无效字符串【记住是一个字串】
    • increment:生成递增的数值类型(每次先查当前的最大的id值+1)
  3. 由开发者维护
    • asigned:必须要有程序员给定id的值,否则报错
二、对象关系映射:一对多映射

需求案例:客户 与 订单的需求关系:典型的一对多的关系

2.1 测试准备

这里我们需要在创建一张表t_order

CREATE TABLE `t_order` (
	`id` INT(10) NOT NULL AUTO_INCREMENT,
	`order_no` VARCHAr(20) NULL DEFAULT NULL COMMENT '订单编号' COLLATE 'utf8mb4_general_ci',
	`product_name` VARCHAr(20) NULL DEFAULT NULL COMMENT '产品名称' COLLATE 'utf8mb4_general_ci',
	`cust_id` INT(10) NULL DEFAULT NULL,
	PRIMARY KEY (`id`) USING BTREE,
	UNIQUE INDEX `t_order_id_uindex` (`id`) USING BTREE,
	INDEX `t_order_t_customer_c_id_fk` (`cust_id`) USING BTREE,
	CONSTRAINT `t_order_t_customer_c_id_fk` FOREIGN KEY (`cust_id`) REFERENCES `hibernate_db`.`t_customer` (`c_id`) ON UPDATE NO ACTION ON DELETE NO ACTION
)
COLLATE='utf8mb4_general_ci'
ENGINE=InnoDB
AUTO_INCREMENT=2;
2.2 创建实体

注意事项:

  1. 需要在Custom实体中先给一个List来关联多方的实体信息

  2. order实体表也需要给一个Custom的JavaBean对其进行关联

【Order】

public class Order implements Serializable {
    private static final long serialVersionUID = 1L;

    private String id; // 订单表主键
    private String orderNo; // 订单编号
    private String prodName; // 产品名称

    private Integer custId; // 外键客户id

    
    private Customer customer;
}
2.3 hbm.xml文件修改

【customer.hbm.xml】
在Custom.hbm.xml文件里,我们需要做的是将order进行关联用set标签


        
            
        
        
        
        
        

        
        
        
            
            
			
            
        
    

一表中的关联配置使用的标签是:

【order.hbm.xml】


        
            
        
        
        

        
        
    

多表中所关联的字段是用的标签是

2.4 编写测试类
    @Test
    public void test1() throws HibernateException {
        // 准备数据
        
        Customer lisi  = new Customer();
        lisi.setName("里斯");
        lisi.setGender("1");
        lisi.setAge(32);
        lisi.setLevel("至尊VIP,年卡8级");
        
        Set orders = new HashSet<>();
        // 订单1
        Order order1 = new Order();
        order1.setOrderNo("20220807111");
        order1.setProdName("小米Ultr11");
        order1.setCustomer(lisi);
        // 订单2
        Order order2 = new Order();
        order2.setOrderNo("20220807134");
        order2.setProdName("华为MateBook_Pro 512G+8G");
        order2.setCustomer(lisi);
        // 客户添加订单
        orders.add(order1);
        orders.add(order2);
        lisi.setOrders(orders);
        
        Session session = HibernateUtil.getConnection();
        //4、开启事务
        Transaction tx = session.beginTransaction();
        //5、执行添加操作
        session.save(lisi);
        session.save(order1);
        session.save(order2);
        //6、提交事务
        tx.commit();
        //7、关闭资源
        HibernateUtil.closeSession(session);
    }

【订单表】

【客户表】

为了可以证实是否插入成功,我么可以再写一个方法来查询某一个客户的订单

    @Test
    public void test2() throws HibernateException {

        Session session = HibernateUtil.getConnection();
        //4、开启事务
        Transaction tx = session.beginTransaction();
        //5、执行添加操作
        Customer customer = session.get(Customer.class, 5);
        System.out.println("用户名称:"+customer.getName());
        Set orders = customer.getOrders();
        for (Order order : orders) {
            System.out.println("订单:"+order.getOrderNo());
        }
        //6、提交事务
        tx.commit();
        //7、关闭资源
        HibernateUtil.closeSession(session);
    }

三、casecode和inverse配置 3.1 CaseCade级联操作

级联操作,就是操作一个对象的时候,相同时操作他的关联对象。

  • 级联保存

     
     
     

【测试】

@Test
    public void test3() throws HibernateException {
        // 准备数据
        Customer lisi = new Customer();
        lisi.setName("马云云");
        lisi.setGender("1");
        lisi.setAge(34);
        lisi.setLevel("至尊VIP,年卡n级");

        Set orders = new HashSet<>();
        // 订单1
        Order order1 = new Order();
        order1.setOrderNo("20220808123");
        order1.setProdName("阿里巴巴");
        order1.setCustomer(lisi);
        // 订单2
        Order order2 = new Order();
        order2.setOrderNo("20220808141");
        order2.setProdName("华强北 只能IPHONE watch");
        order2.setCustomer(lisi);
        // 客户添加订单
        orders.add(order1);
        orders.add(order2);
        lisi.setOrders(orders);

        Session session = HibernateUtil.getConnection();
        //4、开启事务
        Transaction tx = session.beginTransaction();
        //5、执行添加操作
        session.save(lisi); // 保存客户
        // 级联保存订单数据,所以配置在客户的映射文件中
        //6、提交事务
        tx.commit();
        //7、关闭资源
        HibernateUtil.closeSession(session);
    }

  • 级联删除

     
     
     

【测试】

 @Test
    public void test4() throws HibernateException {

        Session session = HibernateUtil.getConnection();
        //4、开启事务
        Transaction tx = session.beginTransaction();
        //5、执行添加操作
        Customer cus = session.get(Customer.class, 6);// 级联删除
        //6、提交事务
        session.delete(cus);
        tx.commit();
        //7、关闭资源
        HibernateUtil.closeSession(session);
    }

如果没有级联删除,则会把外键的值置为空。级联删除则会在删除一个对象的同时将其关联的的对象也删除。


【实现级联操作的注意事项】:

  1. 搞清楚谁级联操作谁?添加A的时候,级联添加B,那么级联操作的就是B,配置就在A

  2. 级联操作的核心是cascade="级联操作的属性"

    • save-update:级联保存
    • delete:级联删除
    • all:级联保存和删除
3.2 INVERSE反转配置

第一次听到这个概念让我想起了Spring的IOC

inverse配置:表示是否把关联表的维护权反转(放弃)

  • true:放弃
  • false:不放弃(不反转)

这里我们可以看一下级联保存的的时候,wmendeHibernate会自动地有两条SQL帮助我们去维护被关联的表


结论:
通常在一对多的关联关系中,多方不能放弃维护权,建议放弃一方,意味着需要在一方加上inverse=true的配置

四、对象关系映射:多对多映射

需求:用户 与 角色的关联关系:多对多的关系

4.1 多对多插入操作 4.1.1 数据库设计

4.1.2 对象设计

【User表】

public class User implements Serializable {

    private Integer id;
    private String name;
	// getter、setter...
 }

【Role表】

public class Role implements Serializable {

    private Integer id;
    private String name;
	// getter、setter...
 }
4.1.3 映射的配置

【Role.hbm.xml】




    
        
        
        
        
        
            
            
            
            
        
      


【User.hbm.xml】




    
        
        
        
        
        
            
            
            
            
        
      


注意事项:

  1. 在配置任意一方的set集合关联字段的时候,我们知道hibernate是默认inverse=false的,这样一来在多对多的关系中,就会出现重复的维护冲突,所以我们需要在任意一方设置inverse=true
  2. 这里建议使用MySQL5的版本,因为hibernate创建表的时候会将存储引擎设置为myisam,如果使用了Mysql8的版本,需要在全局的核心配置文件中设置上
    org.hibernate.dialect.MySQL5InnoDBDialect,否则会报SQL语法错误
  3. 在任意一方配置是都不能配置主键策略,否则无法关联外键的关联关系
  
org.hibernate.dialect.MySQL5InnoDBDialect

4.2 多对多查询
@Test
    public void test6() throws HibernateException {
        // 准备数据

        Session session = HibernateUtil.getConnection();
        //4、开启事务
        Transaction tx = session.beginTransaction();
        //5、执行添加操作
        User user = session.get(User.class, 1);
        System.out.println("当前用户:"+user.getName());
        Set roles1 = user.getRoles();
        for (Role role : roles1) {
            System.out.println("当前用户的角色:"+role.getName());
        }

        User user2 = session.get(User.class, 2);
        System.out.println("当前用户:"+user2.getName());
        Set roles = user2.getRoles();
        for (Role role : roles) {
            System.out.println("当前用户的角色:"+role.getName());
        }
        //6、提交事务
        tx.commit();
        //7、关闭资源
        HibernateUtil.closeSession(session);
    }

4.3 多对多级联添加操作

User.hbm.xml配置


     
     
     
     

注意事项:
1.级联操作就是在任意一方设置casecade=级联配置—> 比如级联保存是save-update

 @Test
    public void test7() throws HibernateException {
        // 准备数据

        Session session = HibernateUtil.getConnection();
        //4、开启事务
        Transaction tx = session.beginTransaction();
        //5、执行添加操作
        User user1 = new User();
        user1.setId(3);
        user1.setName("大公鸡");
        Role r1 = new Role();
        r1.setName("五星红钻");
        r1.setId(3);
        Set roles = new HashSet<>();
        roles.add(r1);
        user1.setRoles(roles);
        
        session.save(user1);
        //6、提交事务
        tx.commit();
        //7、关闭资源
        HibernateUtil.closeSession(session);
    }

不过通常我更偏向于使用all 包括了级联保存和删除

五、对象关系映射:一对一映射

需求:中华人民共和国公民 与 个人身份证 是典型的一对一关系

5.1 数据库设计

5.2 实体类设计 5.2.1 外键关联

【IdCard实体类】

public class IdCard implements Serializable {
    private Integer id;
    private String name;

    private Person person;
	//getter、setter...
}

【Person实体类】

public class Personimplements Serializable {
    private Integer id;
    private String name;

    private IdCard card;
	//getter、setter...
}
5.2.2 主键关联

【IdCard实体类】

public class IdCard implements Serializable {
    private Integer id;
    private String name;

    private Person person;
	//getter、setter...
}

【Person实体类】

public class Personimplements Serializable {
    private Integer id;
    private String name;

    private IdCard card;
	//getter、setter...
}
5.3 配置文件 5.3.1 外键关联

【Person.hbm.xml】




    
        
            
        
        
        
        
      


【IdCard.hbm.xml】




    
        
            
        
        
        
        
      


注意事项

  1. 在一对一的配置中给,我们需要设置任意一方的属性为many-to-one,然后通过核心的unique设置其外键是唯一
5.3.2 主键关联

【Person.hbm.xml】
与外键关联保持一致
【IdCard.hbm.xml】




    
        
            
        
        
        
        
      


注意事项:

  1. 逐渐概念需要使用one-to-one标签 其中使用constraint=”true“配置主键关联
5.4 测试 5.4.1 外键关联
@Test
    public void test8() throws HibernateException {
        // 准备数据
        Person p = new Person();
        p.setName("魏巍");
        IdCard idCard = new IdCard();
        idCard.setName("中华人民共和国个人身份证:61020210213826465456");
        idCard.setPerson(p);
        p.setCard(idCard);
        Session session = HibernateUtil.getConnection();
        //4、开启事务
        Transaction tx = session.beginTransaction();
        //5、执行添加操作
        session.save(p);
        session.save(idCard);

        //6、提交事务
        tx.commit();
        //7、关闭资源
        HibernateUtil.closeSession(session);
    }
5.4.2 主键关联
@Test
    public  void test10(){
        Session session = HibernateUtil.getConnection();

        Transaction tx = session.beginTransaction();
        com.wei.domain.onetoone_pk.Person p = new com.wei.domain.onetoone_pk.Person();

        p.setName("刘虎");
        com.wei.domain.onetoone_pk.IdCard card = new com.wei.domain.onetoone_pk.IdCard();
        card.setName("中国台湾身份证6675677457576386");
        card.setPerson(p);
        p.setCard(card);

        session.save(p);
        session.save(card);

        tx.commit();

        HibernateUtil.closeSession(session);
    }

【至此,第二章的hibernate的学习就此结束】
总结:

  1. 配置文件的方式配置一对一,一对多或者是多对多的关系都比较冗余(个人觉得),后期会学习注解是的JPA开发
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1039767.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号