前言
本章讲解Hibernate的关联关系及其配置方式
方法
1.一对一关联关系
我们之前学过MyBatis,也了解了其关联关系的配置方式。那么Hibernate该如何配置呢?首先我以一对一关联进行讲解!
范例:人和身份证的关系
人和身份证是一对一的关系,也就是说一个人只能拥有一个身份证,一个身份证只属于一个人!
那么,我们首先先建立两个实体类,Person和IDCard,示例代码如下:
package cn.edu.ccut.bo;
import org.hibernate.annotations.GenericGenerator;
import javax.persistence.*;
import java.io.Serializable;
@Entity
public class Person implements Serializable {
@Id
@GenericGenerator(name = "uuid",strategy = "uuid")
@GeneratedValue(generator = "uuid")
private String id;
private String name;
public Person() {
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package cn.edu.ccut.bo;
import org.hibernate.annotations.GenericGenerator;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import java.io.Serializable;
@Entity
public class IDCard implements Serializable {
@Id
@GenericGenerator(name = "uuid",strategy = "uuid")
@GeneratedValue(generator = "uuid")
private String id;
private String code;
public IDCard() {
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
@Override
public String toString() {
return "IDCard{" +
"id='" + id + '\'' +
", code='" + code + '\'' +
'}';
}
}
1)单向一对一关联
我们在Person类中加入关联属性idCard如下:
这个时候,我们需要添加一对一关联关系所使用的注解,那就是@OneToOne
@OneToOne注解解释:
- cascade:关联属性,这个属性定义了当前类对象操作了之后,级联对象的操作。其中CascadeType.ALL,当前类增删改查改变之后,关联类跟着增删改查。
- fetch属性:FetchType类型的属性。可选择项包括:FetchType.EAGER 和FetchType.LAZY。 FetchType.EAGER表示关系类在主类加载的时候同时加载,FetchType.LAZY表示关系类在被访问时才加载。默认值是FetchType.LAZY。
- mappedBy:拥有关联关系的域,如果关系是单向的就不需要,双向关系表,那么拥有关系的这一方有建立、解除和更新与另一方关系的能力,而另一方没有,只能被动管理,这个属性被定义在关系的被拥有方。
这个时候我们通过@OneToOne注解配置Person如下:
package cn.edu.ccut.bo;
import org.hibernate.annotations.GenericGenerator;
import javax.persistence.*;
import java.io.Serializable;
@Entity
public class Person implements Serializable {
@Id
@GenericGenerator(name = "uuid",strategy = "uuid")
@GeneratedValue(generator = "uuid")
private String id;
private String name;
@OneToOne(cascade = CascadeType.ALL,fetch = FetchType.EAGER)
private IDCard iDCard;
public IDCard getIDCard() {
return iDCard;
}
public void setIDCard(IDCard iDCard) {
this.iDCard = iDCard;
}
public Person() {
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", iDCard=" + iDCard +
'}';
}
}
我们在hibernate.cfg.xml配置如下:
<!-- 自动创建|更新|验证数据库表结构 create表示每次删除表新建表,update表示没表新建表,有表直接更新 -->
<property name="hbm2ddl.auto">create</property>
<!-- 配置映射文件路径 -->
<mapping class="cn.edu.ccut.bo.Person"/>
<mapping class="cn.edu.ccut.bo.IDCard"/>
编写测试类如下:
import cn.edu.ccut.bo.IDCard;
import cn.edu.ccut.bo.Person;
import cn.edu.ccut.util.DBUtil;
import org.hibernate.Session;
import org.junit.Test;
public class HibernateTest {
@Test
public void testHibernateConfig() throws Exception{
//创建Session对象
Session session = DBUtil.getSession();
//开启事务
session.beginTransaction();
IDCard idCard = new IDCard();
idCard.setCode("123143");
Person person = new Person();
person.setName("张三");
person.setIDCard(idCard);
session.save(idCard);
session.save(person);
session.getTransaction().commit();
/* Person person = (Person) session.get(Person.class, "297ebee0688a626701688a6269090000");
System.out.println(person);*/
DBUtil.close();
}
}
执行结果如下:
我们通过上面的结果可以发现,默认创建的关联列名称为 关联表名称_关联表主键
但是,一般情况下,我们的关联字段的设置是自定义的,那么可以使用@JoinColumn注解
@JoinColumn注解解释:
- name:定义关联字段的名称
- referencedColumnName:定义参照表的字段(参照表主键)
使用该注解示例如下:
执行结果如下:
2)双向一对一关联
有些时候,我们需要通过人查到其身份证信息,通过身份证信息查到其人员信息,那么就需要双向的一对一关联,IDCard.java编写如下:
mappedBy属性表示关联关系由拥有iDCard属性的Person类进行管理,双向关联务必在被管理方配置该选项!
此时,我们分别对人和身份证分别执行查询,看是否可以查到关联数据!
查询Person类测试代码:
import cn.edu.ccut.bo.IDCard;
import cn.edu.ccut.bo.Person;
import cn.edu.ccut.util.DBUtil;
import org.hibernate.Session;
import org.junit.Test;
public class HibernateTest {
@Test
public void testHibernateConfig() throws Exception{
//创建Session对象
Session session = DBUtil.getSession();
Person person = (Person) session.get(Person.class, "40288d81688c96ce01688c96ed880001");
System.out.println(person);
DBUtil.close();
}
}
执行结果如下:
查询IDCard类代码如下:
import cn.edu.ccut.bo.IDCard;
import cn.edu.ccut.util.DBUtil;
import org.hibernate.Session;
import org.junit.Test;
public class HibernateTest {
@Test
public void testHibernateConfig() throws Exception{
//创建Session对象
Session session = DBUtil.getSession();
IDCard iDCard = (IDCard) session.get(IDCard.class, "40288d81688c96ce01688c96ed7e0000");
System.out.println(iDCard.getPerson());
DBUtil.close();
}
}
特别的:被动管理类不允许重写toString()方法,如本例中IDCard类配置toString()会发生递归调用造成死循环
2.一对多关联关系
一对多的关联关系其实和一对一配置方式一致,只需要注意多的要用集合表示即可!
如人和手机的关系,人可以有多个手机,但是一个手机只能属于一个人,那么我们设置Person类和Phone类如下:
Person设置为上面例子中最初始的例子即可,我们编写下Phone类如下:
package cn.edu.ccut.bo;
public class Phone {
private String id;
private String phoneName;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getPhoneName() {
return phoneName;
}
public void setPhoneName(String phoneName) {
this.phoneName = phoneName;
}
}
我这里直接讲双向的一对多关联关系!
在Phone类中进行如下配置:
package cn.edu.ccut.bo;
import org.hibernate.annotations.GenericGenerator;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
@Entity
public class Phone {
@Id
@GenericGenerator(name = "uuid",strategy = "uuid")
@GeneratedValue(generator = "uuid")
private String id;
private String phoneName;
@ManyToOne
private Person person;
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getPhoneName() {
return phoneName;
}
public void setPhoneName(String phoneName) {
this.phoneName = phoneName;
}
}
Person类进行如下配置:
package cn.edu.ccut.bo;
import org.hibernate.annotations.GenericGenerator;
import javax.persistence.*;
import java.io.Serializable;
import java.util.List;
@Entity
public class Person implements Serializable {
@Id
@GenericGenerator(name = "uuid",strategy = "uuid")
@GeneratedValue(generator = "uuid")
private String id;
private String name;
@OneToMany(mappedBy = "person")
private List<Phone> phones;
public List<Phone> getPhones() {
return phones;
}
public void setPhones(List<Phone> phones) {
this.phones = phones;
}
public Person() {
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", phones=" + phones +
'}';
}
}
编写测试类测试:
import cn.edu.ccut.bo.Person;
import cn.edu.ccut.bo.Phone;
import cn.edu.ccut.util.DBUtil;
import org.hibernate.Session;
import org.junit.Test;
public class HibernateTest {
@Test
public void testHibernateConfig() throws Exception{
//创建Session对象
Session session = DBUtil.getSession();
//开启事务
session.beginTransaction();
Phone p1 = new Phone();
p1.setPhoneName("华为");
Phone p2 = new Phone();
p2.setPhoneName("苹果");
Person person = new Person();
person.setName("张三");
session.save(person);
p1.setPerson(person);
p2.setPerson(person);
session.save(person);
session.save(p1);
session.save(p2);
session.getTransaction().commit();
/*Person person = (Person) session.get(Person.class, "40288d81688c96ce01688c96ed880001");
System.out.println(person);*/
DBUtil.close();
}
}
测试结果如下:
我们进行一下查询操作,查询Person类和它所拥有的手机:
测试类编写如下:
import cn.edu.ccut.bo.Person;
import cn.edu.ccut.bo.Phone;
import cn.edu.ccut.util.DBUtil;
import org.hibernate.Session;
import org.junit.Test;
public class HibernateTest {
@Test
public void testHibernateConfig() throws Exception{
//创建Session对象
Session session = DBUtil.getSession();
Person person = (Person) session.get(Person.class, "40288d81688cb42701688cb428810000");
System.out.println(person);
DBUtil.close();
}
}
测试类执行效果如下:
可见我们成功了!
多对多的配置请私下自主进行学习,使用注解@ManyToMany