所谓的关系映射指的是数据库表与表之间的关联关系,通常我们会把表之间的关系总结为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 admins = new HashSet();
}
此处一对多配置,只配置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 admins = new HashSet();
双向关联是如上配置, 同时需要注意的是,此种配置,我们的关系管理就交给了多端来进行管理了。
所以代码如下:
@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)
所以我们双向关联和单项关联有很多的区别,但是开发当中常用双向关联。