Hibernate配置表关联的方式
一对一(OneToOne)
例如在一张表中,其中有一个列与另一个表对应,并且是唯一对应的关系时就是一对一关系了,通常我们会将这一列作为外键(数据库基础知识),例如新建两张表,一张company表作为公司表,一张Boss表作为老板表,因此这里就是一个公司对应一个老板(公司表里应该要有一个外键列存储老板的id,并且是唯一的),下面使用OneToOne注解配置一下表的关联关系
示例代码:
@Entity(name="company")
public class Company {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private int id;
private String name;
private int number;
@OneToOne(fetch=FetchType.LAZY,targetEntity=Boss.class)
@JoinColumn(name="C_B",unique=true,referencedColumnName="id")
private Boss boss;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
public Boss getBoss() {
return boss;
}
public void setBoss(Boss boss) {
this.boss = boss;
}
}
这是第一张表,因为要关联Boss表,所以加入了一个Boss属性。在@OneToOne注解中,有两个属性,第一个fetch表示加载的方式,FetchType.LAZY表示延迟加载,即当你获取这张表(Company表)的信息时,只会拿到Company表的信息,只有在使用到Boss表的信息时Hibernate才会根据这条数据对应的外键去Boss表查询(这么做有助于提高性能)
还有一个注解@JoinColumn(name="C_B",unique=true,referencedColumnName="id"),即在表中加入了一个列(外键列),name属性申明列名,unique申明唯一性,referencedColumnName表示这个列对应Boss表中的id列
完成后记得在配置文件里配置这两张表的映射
测试类代码:
OnToOne.class
public class OnToOne {
public static void main(String[] args) {
// TODO Auto-generated method stub
MySessionFactory mySessionFactory = new MySessionFactory();
Session session = mySessionFactory.getSession();
Boss boss = new Boss();
boss.setName("马化腾");
session.save(boss);
Company company = new Company();
company.setName("Tencent");
company.setNumber(2000);
company.setBoss(boss);
session.save(company);
mySessionFactory.commit();
mySessionFactory.close();
}
}
测试代码中对两张表各插入了一条数据,必须先插入Boss数据,再拿到这条数据给Company保存,因为后面插入Company数据时还要保存这条数据的外键(Boss这条数据保存时已经变为持久化状态,是有id的)
运行后查看结果,保存成功。如果要测试它的延迟加载机制FetchType.LAZY,可以从Company表中将这条数据取出来,再取出其中的信息(除Boss中的属性)时,控制台只打印了查询Company表的sql语句,而当取出Boss中的信息时,可以看到控制台打印了两条sql语句
一对多(OneToMany)
接下来是表数据一对多的关系,以班级与学生为例:
新建一个Classes类作为班级表:
@Entity(name="classes")
public class Classes {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private int cid;
private String name;
@OneToMany(fetch=FetchType.LAZY,
targetEntity=Student.class,
orphanRemoval=true
cascade=CascadeType.REMOVE)
@JoinColumn(name="FKey_C_S",referencedColumnName="cid")
private Set<Student> students = new HashSet<>();
public int getCid() {
return cid;
}
public void setCid(int cid) {
this.cid = cid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set<Student> getStudents() {
return students;
}
public void setStudents(Set<Student> students) {
this.students = students;
}
}
除了一些基本注解外,需要了解这里的OneToMany注解
@OneToMany(
fetch=FetchType.LAZY, //这个属性即前面写过的懒加载(延迟加载)
targetEntity=Student.class, //这个属性对应实体目标,即对应下面的学生表Student.class
orphanRemoval=true, //删除孤儿记录,下面会测试
cascade=CascadeType.REMOVE //级联删除
)
下面建立Student类作为学生表:
@Entity(name="student")
public class Student {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private int sid;
private String name;
private int age;
public int getSid() {
return sid;
}
public void setSid(int sid) {
this.sid = sid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
写完后还需要在配置文件中配置两张表的映射
测试类代码示例:
public class OnToMany {
public static void main(String[] args) {
// TODO Auto-generated method stub
MySessionFactory mySessionFactory = new MySessionFactory();
Session session = mySessionFactory.getSession();
Student student1 = new Student();
student1.setName("关羽");
student1.setAge(20);
Student student2 = new Student();
student2.setName("秦琼");
student2.setAge(21);
Classes classes1 = new Classes();
classes1.setName("一班");
classes1.getStudents().add(student1);
classes1.getStudents().add(student2);
session.save(student1);
session.save(student2);
session.save(classes1);
mySessionFactory.commit();
mySessionFactory.close();
}
}
运行保存成功,数据表student中保存了两条数据,classes表中保存了一条数据
这里classes表中我们保存的班级那条数据已经跟student表的两条数据关联了,因此可以通过查询这条班级数据来获得关联它的学生数据
示例代码:
public class OnToMany {
public static void main(String[] args) {
// TODO Auto-generated method stub
MySessionFactory mySessionFactory = new MySessionFactory();
Session session = mySessionFactory.getSession();
//查出班级Id为1的数据
Classes classes2 = (Classes) session.get(Classes.class, 2);
System.out.println("学生个数="+classes2.getStudents().size());
mySessionFactory.commit();
mySessionFactory.close();
}
}
运行后控制台打印显示Set集合中有两条数据
测试孤儿删除,即可以通过班级来删除它所关联下的所有学生数据
public class OnToMany {
public static void main(String[] args) {
// TODO Auto-generated method stub
MySessionFactory mySessionFactory = new MySessionFactory();
Session session = mySessionFactory.getSession();
Classes classes1 = (Classes) session.get(Classes.class, 2);
classes1.getStudents().clear();
mySessionFactory.commit();
mySessionFactory.close();
}
}
运行后成功将数据表中关联班级1的两条数据删除
测试级联删除,即在删除班级1时,会同时删除关联了这条数据的学生数据
示例代码:
Classes classes1 = (Classes) session.get(Classes.class, 1);
session.delete(classes1);