【Hibernate框架】关联映射(一对多,多对一)
2018-02-06 14:49
381 查看
场景设定:
国家规定,一个人只能在一个公司上班,一个公司可以拥有很多员工。我们就利用这个场景,根据针对对象的不同,我们分别来分析一下一对多、多对一关联映射。
Po对象:Employee.Java
映射文件:Employee.hbm.xml
值得一提的是,如果我们没有在测试程序里面session.save(company),直接执行程序,我们会报错,但是解决办法绝不是只有这一种,我们还可以在员工Employee映射文件中的<many-to-one/>中配置cascade属性:
Po对象:Employee.java
Company.hbm.xml
Po对象:Company.java
Employee.hbm.xml
2、对于双向的一对多/多对一来说,他们之间本就是互为指向的,只是要注意我们需用的方法的不同来针对不同的地方进行配置。使用set、list的时候,大体上是差不多的,关键就是使用list的时候,多对一从表的逐渐不可自己更添,而一对多从表主/外键id不能为空
转自:http://www.cnblogs.com/DoubleEggs/p/6257644.html
国家规定,一个人只能在一个公司上班,一个公司可以拥有很多员工。我们就利用这个场景,根据针对对象的不同,我们分别来分析一下一对多、多对一关联映射。
一、多对一单向关联映射
1、多对一单向关联映射:对于员工(Employee)来说,他跟公司(Company)的对应关系就是多对一关系Po对象:Employee.Java
public class Employee { public int id; public String name; public Company company; //getter, setter方法 }Company.java
public class Company { public int id; public String name; //getter, setter方法 }作为程序员,我们都知道在设计数据库要在多对一的多那一面添加一的外键,所以我们在员工类中,添加对公司类的引用。
映射文件:Employee.hbm.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="com.hib.domain"> <class name="com.hib.domain.Employee" table="employee"> <id name="id" type="int"> <generator class="native"/> </id> <property name="name"/> <many-to-one name="company" column="company_id"/> </class> </hibernate-mapping>Company.hbm.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.hib.domain.Company" table="company"> <id name="id"> <generator class="native"/> </id> <property name="name"/> </class> </hibernate-mapping>测试:
@Test public void testSaveCompany() { Session session = HibernateUtils.getSession(); Transaction tx = session.beginTransaction(); Company company = new Company(); company.setName("某某集团"); session.save(company);//这里必须要先save一下company,将之变成持久化状态否则会因为无法保存瞬时对象而报错 Employee employee1 = new Employee(); employee1.setName("路人甲"); employee1.setCompany(company); Employee employee2 = new Employee(); employee2.setName("路人乙"); employee2.setCompany(company); session.save(employee1); session.save(employee2); tx.commit(); session.close(); }执行结果:
值得一提的是,如果我们没有在测试程序里面session.save(company),直接执行程序,我们会报错,但是解决办法绝不是只有这一种,我们还可以在员工Employee映射文件中的<many-to-one/>中配置cascade属性:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibe 4000 rnate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="com.hib.domain"> <class name="com.hib.domain.Employee" table="employee"> <id name="id" type="int"> <generator class="native"/> </id> <property name="name"/> <many-to-one name="company" column="company_id" cascade="save-update"/> </class> </hibernate-mapping>
@Test public void testSaveCompany() { Session session = HibernateUtils.getSession(); Transaction tx = session.beginTransaction(); Company company = new Company(); company.setName("某某集团"); // session.save(company);//这里必须要先save一下company,将之变成持久化状态否则会因为无法保存瞬时对象而报错 Employee employee1 = new Employee(); employee1.setName("路人甲"); employee1.setCompany(company); Employee employee2 = new Employee(); employee2.setName("路人乙"); employee2.setCompany(company); session.save(employee1); session.save(employee2); tx.commit(); session.close(); }关于cascade的一些属性值分别是:persist, merge, delete, save-update, evict, replicate, lock, refresh
二、一对多单向关联映射
同样适用上面的场景设定:国家规定一个员工只能在一个公司上班,但是一个公司可以拥有很多员工。这时候,针对公司来说,就是一对多关系了。像这种时候,我们就需要在公司类中添加一个对员工对象的集合了。这个集合可以是set、list、map、array数组的有关容器(其中set中的对象不可重复,相对性能也比较高,建议使用set)Po对象:Employee.java
public class Employee { public int id; public String name; //getter, setter方法 }Company.java
public class Company { public int id; public String name; public Set<Employee> employees; //getter, setter方法 }映射文件:Employee.hbm.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="com.hib.domain"> <class name="com.hib.domain.Employee" table="employee"> <id name="id" type="int"> <generator class="native"/> </id> <property name="name"/> </class> </hibernate-mapping>Company.hbm.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.hib.domain.Company" table="company"> <id name="id"> <generator class="native"/> </id> <property name="name"/> <set name="employees"> <key column="company_id"/><!-- "多"的一方关联"一"的一方的外键 --> <one-to-many class="com.hib.domain.Employee"/><!-- 一个Company对象对应多个Employee对象 --> </set> </class> </hibernate-mapping>测试:
@Test public void testSaveCompany() { Session session = HibernateUtils.getSession(); Transaction tx = session.beginTransaction(); Employee employee1 = new Employee(); employee1.setName("路人甲"); session.save(employee1); Employee employee2 = new Employee(); employee2.setName("路人乙"); session.save(employee2); Set<Employee> employees = new HashSet<>(); employees.add(employee1); employees.add(employee2); Company company = new Company(); company.setName("某某集团"); company.setEmployees(employees); session.save(company); tx.commit(); session.close(); }数据插入之后,我们进行查询:
@Test public void testQueryCompany() { Session session = HibernateUtils.getSession(); Transaction tx = session.beginTransaction(); Company company = session.load(Company.class, 1); System.out.println("公司名称:" + company.getName()); System.out.println("公司员工:"); for (Employee employee : company.getEmployees()) { System.out.print(" " + employee.getName()); } tx.commit(); session.close(); }查询结果:
Hibernate: select company0_.id as id1_0_0_, company0_.name as name2_0_0_ from company company0_ where company0_.id=? 公司名称:某某集团 公司员工: Hibernate: select employees0_.company_id as company_3_1_0_, employees0_.id as id1_1_0_, employees0_.id as id1_1_1_, employees0_.name as name2_1_1_ from employee employees0_ where employees0_.company_id=? 路人乙 路人甲从控制台消息来看,还能延迟加载lazy,那如果我们把配置文件改为:
Company.hbm.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.hib.domain.Company" table="company"> <id name="id"> <generator class="native"/> </id> <property name="name"/> <set name="employees" lazy="false"><!--如果这里将lazy设置成false,将禁止延迟加载,默认为true--> <key column="company_id"/><!-- "多"的一方关联"一"的一方的外键 --> <one-to-many class="com.hib.domain.Employee"/><!-- 一个Company对象对应多个Employee对象 --> </set> </class> </hibernate-mapping>查询结果:
Hibernate: select company0_.id as id1_0_0_, company0_.name as name2_0_0_ from company company0_ where company0_.id=? Hibernate: select employees0_.company_id as company_3_1_0_, employees0_.id as id1_1_0_, employees0_.id as id1_1_1_, employees0_.name as name2_1_1_ from employee employees0_ where employees0_.company_id=? 公司名称:某某集团 公司员工: 路人甲 路人乙
三、多对一/一对多双向关联映射
现在我们还是用上面的场景设定来实现一对多/多对一双向关联:Po对象:Company.java
public class Company { public int id; public String name; public Set<Employee> employees; //getter, setter方法 }Employee.java
public class Employee { public int id; public String name; public Company company; //getter, setter方法 }配置文件:Employee.hbm.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="com.hib.domain"> <class name="com.hib.domain.Employee" table="employee"> <id name="id" type="int"> <generator class="native"/> </id> <property name="name"/> <many-to-one name="company" column="company_id" not-null="true"/> </class> </hibernate-mapping>Company.hbm.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.hib.domain.Company" table="company"> <id name="id"> <generator class="native"/> </id> <property name="name"/> <set name="employees"> <key column="company_id"/> <one-to-many class="com.hib.domain.Employee"/> </set> </class> </hibernate-mapping>如果你使用List(或者其他有序集合类),你需要设置外键对应的key列为 not null,让Hibernate来从集合端管理关联,维护每个元素的索引(通过设置update="false" and insert="false"来对另一端反向操作):
Employee.hbm.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="com.hib.domain"> <class name="com.hib.domain.Employee" table="employee"> <id name="id" type="int"> <generator class="native"/> </id> <property name="name"/> <many-to-one name="company" column="company_id" not-null="true" insert="false" update="false"/> </class> </hibernate-mapping>Company.hbm.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.hib.domain.Company" table="company"> <id name="id"> <generator class="native"/> </id> <property name="name"/> <set name="employees"> <key column="company_id" not-null="true"/> <one-to-many class="com.hib.domain.Employee"/> </set> </class> </hibernate-mapping>假若集合映射的<key>元素对应的底层外键字段是NOT NULL的,那么为这一key元素定义not-null="true"是很重要的。不要仅仅为可能的嵌套<column>元素定义not-null="true",<key>元素也是需要的。
四、总结
1、对于单向的一对多、多对一关联映射,建表时,都是在“多”的一端添加外键指向“一”的一端。而他们的不同点就是维护关系的不同,也可理解为主表变更,由谁指向谁的关系变了。2、对于双向的一对多/多对一来说,他们之间本就是互为指向的,只是要注意我们需用的方法的不同来针对不同的地方进行配置。使用set、list的时候,大体上是差不多的,关键就是使用list的时候,多对一从表的逐渐不可自己更添,而一对多从表主/外键id不能为空
转自:http://www.cnblogs.com/DoubleEggs/p/6257644.html
相关文章推荐
- Hibernate框架--关联映射,一对多,多对多 inverse cascade
- Java的Hibernate框架中一对多的单向和双向关联映射
- 【Hibernate框架】关联映射(一对多,多对一)
- 框架 day32 Hibernate,一级缓存,关联关系映射(一对多,多对多)
- Hibernate一对多关联映射及cascade级联操作
- 【HIbernate框架学习】:Hibernate对象关系映射之单向多对多关联映射
- 【Hibernate框架】关联映射(一对一关联映射)
- 【hibernate框架】关系映射之一对一单项外键关联(Annotation实现)
- 深入解析Java的Hibernate框架中的一对一关联映射
- (转)Hibernate框架基础——一对多关联关系映射
- Hibernate框架之关联映射入门
- 【HIbernate框架学习】:Hibernate对象关系映射之双向多对多关联映射
- Eclipse快速上手Hibernate--7. 关联映射(一对多) (3)
- Eclipse快速上手Hibernate--7. 关联映射(一对多) (1)(摘自javaxmj的blog)
- hibernate 一对多 关系关联映射
- Hibernate的关联映射之多对一、一对多、多对多
- Hibernate一对多及多对一关联映射(三)
- Eclipse快速上手Hibernate--7. 关联映射(一对多) (2)(摘自javaxmj的blog)
- 【Hibernate框架】使用链接表的关联映射(一对多/多对一、单/双向映射)
- hibernate映射一对多,双向关系[关联自身],初学例子四