02hibernate关联映射
前言
在关系型数据库中,多表之间存在着三种关联关系,分别为一对一、一对多和多对多。下面将会介绍到三者之间的关系和实践。
一、关联映射的内容和作用
对象间的关联关系的体现:一对一、一对多、多对一、多对多
ORM怎么描述对象之间的关系(重点)
作用:hibernate是一个完整的ORM框架,对象与对象之间是有关系,自动根据关联关系做相应的持久化操作,以面向对象的思想操作关系型数据库。
二、实践 - 一对多
数据库表的联系
对象的联系:
- 一方:区域District
- 多方:街道Street
1、反向工程
生成的类中,多方有一个Set集合
在生成的District.hbm.xml中删除inverse=“true”(后面讲解到)
2、 测试
新建测试类
1、查询指定区域下所有街道的信息
package com.gec.hiber.junit;
import static org.junit.Assert.*;
import java.util.Set;
import org.hibernate.Session;
import org.junit.Test;
import com.gec.hiber.entity.District;
import com.gec.hiber.entity.Street;
import com.gec.hiber.utils.HibernateSessionUtils;
public class TestDistrict {
//查询指定区域下所有街道的信息
@Test
public void test() {
Session session=HibernateSessionUtils.getSession(); //获取连接
int id=104; //要查询的区域id
District district= (District)session.get(District.class, id);
System.out.println(district.getName());
Set<Street> set=district.getStreets();
for (Street street : set) {
System.out.println("\t"+street.getName());
}
session.close();
}
}
2、查询指定街道的信息和街道所属的区域
//查询指定街道的信息和街道所属的区域
@Test
public void test2() {
Session session=HibernateSessionUtils.getSession(); //获取连接
int id=149; //要查询的街道id
Street street= (Street)session.get(Street.class, id);
System.out.println(street.getName());
District district=(street.getDistrict());
System.out.println("\t"+district.getName());
session.close();
}
3、新增一个区域,同时街道也要分配
//新增一个区域,同时街道也要分配
@Test
public void testadd() {
Session session=HibernateSessionUtils.getSession(); //获取连接
Transaction tx=session.beginTransaction(); //开启事务
//创建区域对象 临时状态
District district=new District();
district.setName("X区");
//创建两条街道
Street s1=new Street();
s1.setName("X区-街道1");
Street s2=new Street();
s2.setName("X区-街道2");
//设置对象向之间的关联关系
district.getStreets().add(s1);
district.getStreets().add(s2);
s1.setDistrict(district);
s2.setDistrict(district);
//持久化操作,先加一方,再加多方
session.save(district);
session.save(s1);
session.save(s2);
tx.commit();
session.close();
}
运行结果:出现了多余的update语句,用于修正外键列,影响性能。
解决办法(优化):指定多方来维护外键列,但是默认是一方来维护的。
在District.hbm.xml中修改
<set name="streets" inverse="true" cascade="all">
inverse=false 默认设置,表示 关联维护方是当前方,就是一方来维护,会出现多余的update语句,用于修改多方表的外键列
inverse=true 反转的意思,由当前方的对方(多方)来维护外键列,减少update语句,改善性能。
级联操作:
三、实践 - 多对多
1、反向工程
- employ和project添加对应的类名和自增长
- r_emp_proj不需要添加
更新了两个实体文件和两个orm映射文件
Employ和Project都各自带有Set集合
2、测试
新增项目,分配现在的两名员工负责
package com.gec.hiber.junit;
import static org.junit.Assert.*;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
import com.gec.hiber.entity.Employ;
import com.gec.hiber.entity.Project;
import com.gec.hiber.utils.HibernateSessionUtils;
public class TestProjectEmp {
//新增项目,分配现在的两名员工负责
@Test
public void testManyToMany() {
Session session = HibernateSessionUtils.getSession();
Transaction tx = session.beginTransaction();
Project project = new Project();
project.setProjectname("学习管理系统");
project.setProjectdesc("very good");
//查找两名现有的员工
Employ emp1 = (Employ) session.get(Employ.class, 7);
Employ emp2 = (Employ) session.get(Employ.class, 9);
//设置关联关系
project.getEmploies().add(emp1);
project.getEmploies().add(emp2);
emp1.getProjects().add(project);
emp2.getProjects().add(project);
//持久化的操作
session.save(project);
tx.commit();
HibernateSessionUtils.closeSession();
}
}
测试成功
四、实践 - 一对一
car汽车表,carport车位表。其中car表的主键,同时又是carport表的外键列
1、反向工程
修改为one-to-one
在生成的car.hbm.xml中添加上carport的外键
2、测试
package com.gec.hiber.junit;
import static org.junit.Assert.*;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
import com.gec.hiber.entity.Car;
import com.gec.hiber.entity.Carport;
import com.gec.hiber.utils.HibernateSessionUtils;
public class TestCar {
//新增车位和汽车
@Test
public void testOneToOne() {
Session session=HibernateSessionUtils.getSession(); //获取连接
Transaction tx = session.beginTransaction(); //开启事务
Carport carport = new Carport();
carport.setLocation("X区101");
carport.setCpsize("1000");
Car car = new Car();
car.setNum("粤AE88888");
car.setBrand("五菱宏光");
//设置关联关系
carport.setCar(car);
car.setCarport(carport);
//先保存车位
session.save(carport);
session.save(car);
tx.commit();
session.close();
}
}
运行结果