hibernate----one-to-many

本文介绍Hibernate框架中一对多关联的实现方式,包括双向关联和单向关联两种情况,并通过具体的学生和班级实例来演示如何进行数据的保存、修改及查询。
hibernate里的一对多one-to-many(以学生和班级为例子)
[color=red]1.双向关联情况下[/color]

Classes.java:


package com.domain;

import java.util.HashSet;
import java.util.Set;

public class Classes implements java.io.Serializable {


private Integer id;

private String name;

private Set students = new HashSet(0);

public Classes() {
}

public Classes(String name) {
this.name = name;
}

public Classes(String name, Set students) {
this.name = name;
this.students = students;
}

public Integer getId() {
return this.id;
}

public void setId(Integer id) {
this.id = id;
}

public String getName() {
return this.name;
}

public void setName(String name) {
this.name = name;
}

public Set getStudents() {
return this.students;
}

public void setStudents(Set students) {
this.students = students;
}

}


Student.java


package com.domain;

public class Student implements java.io.Serializable {

private Integer id;

private Classes classes;

private String name;

public Student() {
}

public Student(String name) {
this.name = name;
}

public Student(Classes classes, String name) {
this.classes = classes;
this.name = name;
}

public Integer getId() {
return this.id;
}

public void setId(Integer id) {
this.id = id;
}

public Classes getClasses() {
return this.classes;
}

public void setClasses(Classes classes) {
this.classes = classes;
}

public String getName() {
return this.name;
}

public void setName(String name) {
this.name = name;
}

}


Classes.hbm.xml



<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
<class name="com.domain.Classes" table="classes" catalog="hibernatetest">
<id name="id" type="java.lang.Integer">
<column name="id" />
<generator class="native" />
</id>
<property name="name" type="java.lang.String">
<column name="name" not-null="true" />
</property>
<!-- inverse="true" 主动权反转给了Classes,cascade="all"级联students表里的数据会级联被删除或更新等,这里设置的是all,lazy="true" students表里的数据会lazy加载 -->
<set name="students" inverse="true" cascade="all" lazy="true">
<key>
<column name="classId" />
</key>
<one-to-many class="com.domain.Student" />
</set>
</class>
</hibernate-mapping>


Student.hbm.xml



<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
<class name="com.domain.Student" table="student" catalog="hibernatetest">
<id name="id" type="java.lang.Integer">
<column name="id" />
<generator class="native" />
</id>
<!-- cascade="all" classes表里的数据会被级联操作 fetch="select" classes表里的数据会以左外连接的形式取出来(根据学生查找班级的具体信息时),如果值是join 则进行内连接-->
<many-to-one name="classes" class="com.domain.Classes" fetch="select" cascade="all">
<column name="classId" />
</many-to-one>
<property name="name" type="java.lang.String">
<column name="name" not-null="true" />
</property>
</class>
</hibernate-mapping>


测试类

package com.dao;


import java.util.Iterator;
import java.util.Set;

import org.hibernate.Hibernate;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;

import com.domain.Classes;
import com.domain.Student;

public class Test {
public static void main(String[] args){
Session session = HibernateSessionFactory.getSession();
Transaction tx = session.beginTransaction();
//添加数据
/*

//定义学生一
Student student1 = new Student();
student1.setName("zhansan");
//定义学生二
Student student2 = new Student();
student2.setName("lisi");

//定义班级0201班
Classes classes = new Classes();
classes.setName("0201");
//双向关联给主表设置关联
classes.getStudents().add(student1);
classes.getStudents().add(student2);

//双向关联给从表设置关联
student1.setClasses(classes);
student2.setClasses(classes);

session.save(classes);

tx.commit();
session.close();
*/

//修改多方
//修改学生,必须给要修改的这个学生每个属性都赋值
/*Student student = new Student();
student.setName("wangwu111");
student.setId(1);

Classes classes = new Classes();
classes.setId(1);
classes.setName("0201");
//如果下面这句代码不要的话,则修改执行的sql为update hibernatetest.student set classId=?, name=? where id=?,修改后classId为null(即使classId原来有值,也会被改为null),所以,必须给要修改的这个学生每个属性都赋值
student.setClasses(classes);

//修改
session.update(student);

tx.commit();
session.close();*/
//修改执行的sql:
/*
Hibernate: update hibernatetest.student set classId=?, name=? where id=?
Hibernate: update hibernatetest.classes set name=? where id=?
级联修改
*/



//修改一方,不需要给Set集合属性赋值
/*
Classes classes = new Classes();
classes.setId(1);
classes.setName("0210");
//修改
session.update(classes);

tx.commit();
session.close();*/
//执行的sql:Hibernate: update hibernatetest.classes set name=? where id=?

//查询操作
String hql = "from Classes c where c.id=1";
Query query = session.createQuery(hql);
Classes classes = (Classes)query.uniqueResult();
System.out.println(classes.getId() + " : " + classes.getName() + " : ");
//如果再这里进行session.close();那么需要写下面的判断,强制性去拿student表里的数据
// if(!Hibernate.isInitialized(classes.getStudents())){
// Hibernate.initialize(classes.getStudents());
// }

//因为Student设置的lazy,执行下面的语句时,才去student表查询
Set set = classes.getStudents();
Iterator iterator = set.iterator();
while(iterator.hasNext()){
Student cla = (Student)iterator.next();
System.out.println(cla.getId() + " : " + cla.getName());
}
session.close();
//执行的sql
/*
Hibernate: select classes0_.id as id1_, classes0_.name as name1_ from hibernatetest.classes classes0_ where classes0_.id=1
1 : 0210 :
Hibernate: select students0_.classId as classId1_, students0_.id as id1_, students0_.id as id0_0_, students0_.classId as classId0_0_, students0_.name as name0_0_ from hibernatetest.student students0_ where students0_.classId=?
2 : zhansan
1 : wangwu111
*/
}

}



根据学生查找班级:


package com.dao;

import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;

import com.domain.Student;

public class TestSelect {

public static void main(String[] args) {
Session session = HibernateSessionFactory.getSession();
String hql = "from Student s where s.classes.id=1";
Query query = session.createQuery(hql);
List<Student> list = query.list();

for(int i=0;i<list.size();i++){
Student student = (Student)list.get(i);
System.out.println(student.getId() + " : " + student.getName() + " : " + student.getClasses().getId() + " : " + student.getClasses().getName());

//执行的sql:Hibernate: select student0_.id as id0_, student0_.classId as classId0_, student0_.name as name0_ from hibernatetest.student student0_ where student0_.classId=1
//System.out.println(student.getId() + " : " + student.getName());
}

session.close();
/**
执行的sql为:
Hibernate: select student0_.id as id0_, student0_.classId as classId0_, student0_.name as name0_ from hibernatetest.student student0_ where student0_.classId=1
Hibernate: select classes0_.id as id1_0_, classes0_.name as name1_0_ from hibernatetest.classes classes0_ where classes0_.id=?



*/

}

}




[color=red]2.单向关联情况下[/color]

把一方的Set集合去掉,对应的.hbm.xml里的部分也给去掉。
即去掉:

<set name="students" inverse="true" cascade="all" lazy="true">
<key>
<column name="classId" />
</key>
<one-to-many class="com.domain.Student" />
</set>


测试类:

package com.dao;

import org.hibernate.Session;
import org.hibernate.Transaction;

import com.domain.Classes;
import com.domain.Student;

public class TestInsert {

public static void main(String[] args) {
Session session = HibernateSessionFactory.getSession();
Transaction tx = session.beginTransaction();
//定义班级0201班
Classes classes = new Classes();
classes.setName("0201test");

//定义学生一
Student student1 = new Student();
student1.setName("zhansantest");
student1.setClasses(classes);
//定义学生二
Student student2 = new Student();
student2.setName("lisitest");
student2.setClasses(classes);

//classes一定要最先被save
session.save(classes);
session.save(student1);
session.save(student2);

tx.commit();
session.close();
/**
执行的sql:
Hibernate: insert into hibernatetest.classes (name) values (?)
Hibernate: insert into hibernatetest.student (classId, name) values (?, ?)
Hibernate: insert into hibernatetest.student (classId, name) values (?, ?)
*/




}

}

Hibernate 中,`many-to-one` 关系用于表示数据库中两个实体之间的多对一关联。例如,多个订单(Order)可以属于一个客户(Customer)。在这种情况下,`Order` 类将包含一个指向 `Customer` 的引用,而 `Customer` 类将包含一个 `Order` 的集合。这种关系是双向的,但在 Hibernate 中,通常建议只在关系的“所有者”一方维护这种关系。 ### Many-to-One 关系示例 假设我们有两个实体:`Customer` 和 `Order`。每个 `Order` 都关联到一个 `Customer`,而一个 `Customer` 可以有多个 `Order`。 #### 实体类定义 ```java // Customer.java public class Customer { private int id; private String name; private Set<Order> orders = new HashSet<>(); // Getters and Setters } // Order.java public class Order { private int id; private String details; private Customer customer; // Getters and Setters } ``` #### Hibernate 映射文件 在 Hibernate 的 XML 映射文件中,我们需要定义 `many-to-one` 关系。在这个例子中,`Order` 是关系的所有者,因为它包含了指向 `Customer` 的外键。 ```xml <!-- Customer.hbm.xml --> <hibernate-mapping> <class name="Customer" table="customer"> <id name="id" column="id"> <generator class="native"/> </id> <property name="name" column="name"/> <!-- 由于 Customer 是关系的反方,我们使用 inverse="true" --> <set name="orders" inverse="true"> <key column="customer_id"/> <one-to-many class="Order"/> </set> </class> </hibernate-mapping> <!-- Order.hbm.xml --> <hibernate-mapping> <class name="Order" table="order"> <id name="id" column="id"> <generator class="native"/> </id> <property name="details" column="details"/> <!-- many-to-one 关系定义 --> <many-to-one name="customer" class="Customer" column="customer_id" not-null="true"/> </class> </hibernate-mapping> ``` 在 `Customer` 的映射文件中,`<set>` 元素中的 `inverse="true"` 表示 `Customer` 不负责维护关系,而是由 `Order` 来维护。这意味着当我们保存 `Customer` 时,Hibernate 不会自动更新 `Order` 表中的外键。 ### 使用示例 当创建一个新的 `Order` 并将其关联到一个 `Customer` 时,代码可能如下所示: ```java Session session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); Customer customer = new Customer(); customer.setName("John Doe"); Order order = new Order(); order.setDetails("Order Details"); order.setCustomer(customer); // 设置关系 session.save(customer); session.save(order); tx.commit(); session.close(); ``` 在这个例子中,`Order` 对象通过 `setCustomer` 方法与 `Customer` 建立了关联。由于 `Order` 是关系的所有者,因此保存 `Order` 时,Hibernate 会正确地更新外键。 ### 总结 在 Hibernate 中,`many-to-one` 关系是通过在实体类中添加对另一个实体的引用,并在映射文件中使用 `<many-to-one>` 元素来定义的。为了确保数据的一致性和避免重复的更新操作,应该明确指定哪一方是关系的所有者。通常情况下,拥有外键的那一方应该是关系的所有者。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值