hibernate关系映射管理(一对多,多对一,一对一,多对多)

1、什么是关系映射

所谓的关系映射指的是数据库表与表之间的关联关系,通常我们会把表之间的关系总结为4种,一对一,一对多,多对一,多对多。 这里面我们数据库通常是通过外键和关联表来进行表示的。而对于我们hiberante来说,也需要通过相应的配置去管理这种关系。
我们hibernate通过这种能表现关联关系的配置去创建表的时候,就可以在表结构上把这种关联关系给创建出来

1、一对多
首先我们先理解一对多的什么意思,在数据库A表上的一条数据,可以映射B表的多条数据库,也就是站在A表的角度,就被B表的都跳数据引用,
hiberante就认为A表拥有一个B表的集合,所以配置如下

 package com.xingxue.entity;

import java.util.Date;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.Table;

//关联我们的表

@Entity  //该类被hibernate当做实体给管理
@Table(name="xx_plat_role")   //对应数据库的表
public class Role {

    @Id         //配置主键
    @GeneratedValue(strategy=GenerationType.IDENTITY)  //自增策略
    @Column(name="role_id")  //关联字段名和数据类型
    private int id;

    @Column(name="role_name")  //关联字段名和数据类型
    private String name;
    @Column(name="role_status")  //关联字段名和数据类型
    private String status;
    @Column(name="createdate", columnDefinition="DATETIME")  //关联字段名和数据类型
    private Date createdate;

    @OneToMany   //一对多配置,
    @JoinColumn(name="admin_role")  // 外键的名字
    private Set<Admin> admins = new HashSet<Admin>();

}

此处一对多配置,只配置1端,多端不用管理,所以Admin不需要任何配置
测试代码:

public boolean add(Admin param, int roleId) {
        Session session = this.sessionFactory.openSession();
        //开启事务
        Transaction t = session.beginTransaction();
        //get我们的role对象,让hibernate管理起来
        Role role = (Role) session.get(Role.class, roleId);
        //关联role和admin的关系
        role.getAdmins().add(param);

        int result = (Integer) session.save(param);
        //提交事务
        t.commit();
        //关闭回话
        session.close();
        return result > 0;
    }  

结果如下
这里写图片描述

根据测试结果我们发现,如果我们想要关联两张表的关系,:
1、hibernate配置了关联关系
2、当操作数据的时候,两个关联对象被hibernate管理起来,
3、两个对象之间必须建立关联关系

查询数据测试

@Override
    public List<Role> list() {
        Session session = this.sessionFactory.openSession();
        String SQL = "select * from xx_plat_role";
        List<Role> list = session.createSQLQuery(SQL).addEntity(Role.class).list();
        return list;
    }

结果如下:
这里写图片描述
我们发现在查询role的时候,实际上hibernate自动帮我们查询了当前role下面的所有admin信息,并且封装到了set里面,也就是数据已经包装好了。省去了我们以前的链接查询的操作。
但是通过测试我们发现,在查admin的时候没有把admin相关的role给查询出来,那是因为admin没有配置映射关系,多对一,所以admin无效果,

懒加载设置
其实有的时候我们不需要查询admin信息,所以关联数据hiberante默认使用懒加载机制,所谓的懒加载就是我们需要使用这个数据他 才去查询,你不使用,H就不查询,但是必须建立在session不关闭的情况下,

    @OneToMany(fetch=FetchType.EAGER)   //没有懒加载,
    @OneToMany(fetch=FetchType.LAZY)   //使用懒加载,

由于不使用懒加载效率很低,所以我们默认都使用懒加载,如果在dao有需要进行关联数据加载,建议手动用代码访问一下关联数据

2、多对一

多对一实际上就是和一对多站的角度不一样,表之间的关系,如果是一对多,我们换个角度就是多对一,所以一般一对多和多对一都是双向关联配置,还是Admin和role为例
站在admin的角度多对一:

@Table(name="xx_plat_admin")
public class Admin {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name="admin_id")
    private int id;

    @Column(name="admin_username",length=20)
    private String userName;

    @Column(name="admin_pwd",length=20)
    private String pwd;

    @ManyToOne
    @JoinColumn(name="admin_role")
    private Role role;
@Entity  //该类被hibernate当做实体给管理
@Table(name="xx_plat_role")   //对应数据库的表
public class Role {

    @Id         //配置主键
    @GeneratedValue(strategy=GenerationType.IDENTITY)  //自增策略
    @Column(name="role_id")  //关联字段名和数据类型
    private int id;

    @Column(name="role_name")  //关联字段名和数据类型
    private String name;
    @Column(name="role_status")  //关联字段名和数据类型
    private String status;
    @Column(name="createdate", columnDefinition="DATETIME")  //关联字段名和数据类型
    private Date createdate;

    @OneToMany(mappedBy="role", fetch=FetchType.LAZY)   //一对多配置,
    private Set<Admin> admins = new HashSet<Admin>();

双向关联是如上配置, 同时需要注意的是,此种配置,我们的关系管理就交给了多端来进行管理了。
所以代码如下:

@Override
    public boolean add(Admin param, int roleId) {
        Session session = this.sessionFactory.openSession();
        //开启事务
        Transaction t = session.beginTransaction();
        //get我们的role对象,让hibernate管理起来
        Role role = (Role) session.get(Role.class, roleId);
        //关联role和admin的关系
//      role.getAdmins().add(param);
        param.setRole(role);

        int result = (Integer) session.save(param);
        //提交事务
        t.commit();
        //关闭回话
        session.close();
        return result > 0;
    }

多对一默认不是用懒加载,如果需要使用。需要手动开启

@ManyToOne(fetch=FetchType.LAZY)

所以我们双向关联和单项关联有很多的区别,但是开发当中常用双向关联。

猜你喜欢

转载自blog.csdn.net/sky274548769/article/details/78729250