Hibernate关联映射
关联关系
类与类之间最普遍的关系就是关联关系
hibernate中的关联关系有四种:一对一、一对多、多对一、多对多。
关联关系中又分为单向关联与双向关联
关联关系中又分为单向关联与双向关联
单向关联:单向关联是指只有一方有另一方的关联信息而另一方没有关联信息 例:
A——>B
A对象中有B对象的关联信息
B对象中没有A对象的关联信息
我们可以通过A对象中B的关联信息查询或修改B对象的信息但无法通过B对象来查询修改A对象的信息
同理A<——B也是单向关联
这种只是单方面的关联我们称为单向关联
双向关联:双向关联是指两方都有另一方的关联信息
例:
A<——>B
A对象中有B对象的关联信息
B对象中也有A对象的关联信息
我们可以通过A对象中B的关联信息查询或修改B对象的信息也可以通过B对象来查询修改A对象的信息
这种两方都有另一方的关联信息我们称为双向关联
单向关联一般在一方配置多方不进行配置
如:一对多 单向关联在“一”的一方配置文件里进行配置,”多”的一方不进行配置
双向关联两方都要配置
如:一对多 双向关联在“一”的一方配置文件里需要配置,“多”的一方也需要进行配置
多对一单向关联
Dept:
1 public class Dept { 2 private Integer deptno; 3 private String dname; 4 }
Dept.hbm.xml:
1 <?xml version="1.0"?> 2 <!DOCTYPE hibernate-mapping PUBLIC 3 "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 4 "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 5 6 <hibernate-mapping package="cn.hibernate.day04mapping.manytoone"> 7 <!--实体 name=实体端内容 column=DB端内容--> 8 <class name="Dept" table="DEPT" dynamic-update="true" schema="liutao"> 9 <!--底层数据表对应的主键--> 10 <id name="deptno" column="DEPTNO"> 11 <!--主键生成策略: assigned 程序员手动给值--> 12 <generator class="native"/> 13 </id> 14 <property name="dname" column="DNAME"></property> 15 </class> 16 17 </hibernate-mapping>
Emp:
1 public class Emp { 2 private Integer empno; 3 private String ename; 4 private Dept dept; 5 }
Emp.hbm.xml
1 <?xml version="1.0"?> 2 <!DOCTYPE hibernate-mapping PUBLIC 3 "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 4 "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 5 <hibernate-mapping package="cn.hibernate.day04mapping.manytoone"> 6 <!--实体 name=实体端的内容 column=DB端的内容--> 7 <class name="Emp" table="EMP" schema="liutao"> 8 <!--和底层数据表对应的主键 业务意义--> 9 <id name="empno" column="EMPNO"> 10 <generator class="native"></generator> 11 </id> 12 <property name="ename" column="ENAME"></property> 13 <many-to-one name="dept" class="Dept" column="deptno"></many-to-one> 14 </class> 15 </hibernate-mapping>
单元测试:
1 //关联查询 多对一单项关联 2 @Test 3 public void t1(){ 4 //工具类 5 Session session = HibernateUtil.getSession(); 6 //提供一个员工编号 7 Emp emp = session.load(Emp.class, 20); 8 System.out.println(emp); 9 System.out.println(emp.getEname()); 10 //员工所属部门 11 System.out.println(emp.getDept().getDname()); 12 } 13 14 //保存部门和员工 15 @Test 16 public void t2(){ 17 //工具类 18 Session session = HibernateUtil.getSession(); 19 //开启事务 20 Transaction tx=session.beginTransaction(); 21 //实例化dept 22 Dept dept=new Dept(); 23 dept.setDname("后勤部666"); 24 Emp emp=new Emp(); 25 emp.setEname("孙俪"); 26 //设置员工所属的部门 27 emp.setDept(dept); 28 session.save(dept); 29 session.save(emp); 30 tx.commit(); 31 session.close(); 32 } 33 //按照指定的部门对象查询相关的员工对象 34 @Test 35 public void t3(){ 36 Session session = HibernateUtil.getSession(); 37 String hql="from Emp e where e.dept.deptno=15"; 38 Query query = session.createQuery(hql); 39 List<Emp> list = query.list(); 40 for (Emp emps:list 41 ) { 42 System.out.println("所属员工:"+emps.getEname()); 43 } 44 } 45 //输出指定emps集合中所有emp对象及所关联的部门对象信息 46 @Test 47 public void t4(){ 48 Session session = HibernateUtil.getSession(); 49 String hql="from Emp"; 50 Query query = session.createQuery(hql); 51 List<Emp> list = query.list(); 52 for (Emp emps:list 53 ) { 54 System.out.println("部门名称:"+emps.getDept().getDname()); 55 System.out.println("所属员工为:"+emps.getEname()); 56 } 57 } 58 //;修改编号为1的员工所属部门 59 @Test 60 public void t5(){ 61 //工具类 62 Session session = HibernateUtil.getSession(); 63 //开启事务 64 Transaction tx=session.beginTransaction(); 65 Emp emp = session.load(Emp.class, 18); 66 Dept dept=new Dept(); 67 dept.setDeptno(15); 68 emp.setDept(dept); 69 dept.getEmps().add(emp); 70 tx.commit(); 71 72 session.close(); 73 }
一对多双向关联
Dept.hbm.xml
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="cn.hibernate.day04mapping.manytoonedouble"> <!--实体 name=实体端内容 column=DB端内容--> <class name="Dept" table="DEPT" dynamic-update="true" schema="liutao"> <!--底层数据表对应的主键--> <id name="deptno" column="DEPTNO"> <!--主键生成策略: assigned 程序员手动给值--> <generator class="native"/> </id> <property name="dname" column="DNAME"></property> <set name="emps" cascade="save-update" inverse="false"> <key column="deptno"></key> <one-to-many class="Emp"></one-to-many> </set> </class> </hibernate-mapping>
Emp.hbm.xml
1 <?xml version="1.0"?> 2 <!DOCTYPE hibernate-mapping PUBLIC 3 "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 4 "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 5 <hibernate-mapping package="cn.hibernate.day04mapping.manytoonedouble"> 6 <!--实体 name=实体端的内容 column=DB端的内容--> 7 <class name="Emp" table="EMP" schema="liutao"> 8 <!--和底层数据表对应的主键 业务意义--> 9 <id name="empno" column="EMPNO"> 10 <generator class="native"></generator> 11 </id> 12 <property name="ename" column="ENAME"></property> 13 <many-to-one name="dept" class="Dept" column="deptno"></many-to-one> 14 </class> 15 </hibernate-mapping>
单元测试:
1 @Test 2 public void t6(){ 3 //通过部门查询该部分下所有员工信息(设置从部门到员工的一级关联) 4 String hql="from Dept"; 5 Session session = HibernateUtil.getSession(); 6 Query query = session.createQuery(hql); 7 List<Dept> list = query.list(); 8 for (Dept item:list 9 ) { 10 System.out.println("========================"); 11 System.out.println(item.getDname()); 12 for (Emp emps:item.getEmps() 13 ) { 14 System.out.println(emps.getEname()); 15 } 16 System.out.println("===========END=============="); 17 } 18 //通过某个员工获取员所在部门(设置从员工到部门的多对一关联) 19 Emp emps = session.load(Emp.class, 18); 20 System.out.println(emps.getDept().getDname()); 21 } 22 //添加部门同时添加员工 23 @Test 24 public void t7(){ 25 Session session = HibernateUtil.getSession(); 26 Transaction tran = session.beginTransaction(); 27 //准备一个emp对象 28 Dept dept=new Dept(); 29 dept.setDname("餐饮部"); 30 //准备一个emp对象 31 Emp emp=new Emp(); 32 emp.setEname("张三"); 33 dept.getEmps().add(emp); 34 session.save(dept); 35 // 事务提交 36 tran.commit(); 37 }
关联标记属性
简单介绍下面几个,除了name是必须,其余都是可选的。更多的我们参考官文档。
name=”植入集合的集合名”
column=”映射到本表的字段名”
class=”映射到本表的实体类”
unique=”ture|false”:(数据库外键字段生成一个唯一约束)
not-null=”ture|false”默认false(数据库外键字段是否允许为空值)
lazy=”ture|false”默认proxy(延迟加载)
关于cascade(级联)属性
级联的意思是指定两个对象之间的操作联动关系,对一个对象执行了操作之后,对其指定的级联对象也需要执行相同的操作
总共可以取值为:all、none、save-update、delete
all-代表在所有的情况下都执行级联操作
none-在所有情况下都不执行级联操作
save-update-在保存和更新的时候执行级联操作
delete-在删除的时候执行级联操作
inverse属性
反转,主要用在一对多,多对对双向关联上,inverse可以设置到<set>集合上, 默认inverse为false。为true表示反转,由对方负责;反之,不反转,自己负责;如果不设,one和many两方都要负责控制,因此,会引发重复的sql语句以及重复添加数据。