以Teacher和Student为例,他们之间是多对多的关系。
手动创建的数据库的三张表为,teacher、student、teacher_student。分别如下:
CREATE TABLE `teacher` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(45) DEFAULT '',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `student` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(45) DEFAULT '',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `teacher_student` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`teacher_id` int(11) DEFAULT NULL,
`student_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Teacher类如下:
public class Teacher {
private Long id;
private String name;
private Set<Student> students;
//省略get、set方法
}
Teacher类对应的映射文件Teacher.hbm.xml:
<hibernate-mapping>
<class name="com.ligang.domain.Teacher" table="teacher">
<id name="id" column="id" type="long">
<generator class="identity"/>
</id>
<property name="name" column="name" type="string"/>
<set name="students" table="teacher_student">
<key column="teacher_id"></key>
<many-to-many class="com.ligang.domain.Student" column="student_id"></many-to-many>
</set>
</class>
</hibernate-mapping>
其中set标签的name指的是Teacher类的students属性,table指的是该属性要关联到哪张表。内部的key标签的column指的是该Teacher类所属的表的主键id作为teacher_student的外键teacher_id值。<many-tomany>标签指的是Student类所属的student表的主键作为teacher_student表的student_id值。
Stusent类如下:
public class Student {
private Long id;
private String name;
private Set<Teacher> teachers;
//省略get、set方法
}
Student类对应的映射文件Student.hbm.xml如下:
<hibernate-mapping>
<class name="com.ligang.domain.Student" table="student">
<id name="id" column="id" type="long">
<generator class="identity"/>
</id>
<property name="name" column="name" type="string"/>
<set name="teachers" table="teacher_student" inverse="true">
<key column="student_id"></key>
<many-to-many class="com.ligang.domain.Teacher" column="teacher_id"></many-to-many>
</set>
</class>
</hibernate-mapping>
其中的set映射关系同上。
然后就来看下增添方法:
@Test
public void testAddTeacher1(){
Session session=hibernateDao.getSession();
Transaction tx=session.beginTransaction();
Teacher t=new Teacher();
t.setName("teacher4");
Student s1=new Student();
s1.setName("assa");
Student s2=new Student();
s2.setName("sdfvdv");
Set<Student> students=new HashSet<Student>();
students.add(s1);
students.add(s2);
t.setStudents(students);
session.save(s1);
session.save(s2);
session.save(t);
tx.commit();
session.close();
}
三个save,三个insert语句,同时,由于t.setStudents(students),所以teacher会去维护teacher_student关系表,所以又会增添两条insert语句,sql如下:
Hibernate: insert into hibernate.student (name) values (?)
Hibernate: insert into hibernate.student (name) values (?)
Hibernate: insert into hibernate.teacher (name) values (?)
Hibernate: insert into hibernate.teacher_student (teacher_id, student_id) values (?, ?)
Hibernate: insert into hibernate.teacher_student (teacher_id, student_id) values (?, ?)
如果增添改为如下状态:
@Test
public void testAddTeacher(){
Session session=hibernateDao.getSession();
Transaction tx=session.beginTransaction();
Teacher t=new Teacher();
t.setName("teacher4");
Student s1=new Student();
s1.setName("assa");
Student s2=new Student();
s2.setName("sdfvdv");
Set<Student> students=new HashSet<Student>();
Set<Teacher> teachers=new HashSet<Teacher>();
students.add(s1);
students.add(s2);
teachers.add(t);
t.setStudents(students);
s1.setTeachers(teachers);
s2.setTeachers(teachers);
session.save(s1);
session.save(s2);
session.save(t);
tx.commit();
session.close();
}
此时,不仅建立起了t.setStudents(students)关系,同时s1.setTeachers(teachers);s2.setTeachers(teachers);也建立了关系,所以最终事务提交的时候,teacher、student都会去维护teacher_student表,造成了4个insert语句,造成了重复。如下:
Hibernate: insert into hibernate.student (name) values (?)
Hibernate: insert into hibernate.student (name) values (?)
Hibernate: insert into hibernate.teacher (name) values (?)
Hibernate: insert into hibernate.teacher_student (student_id, teacher_id) values (?, ?)
Hibernate: insert into hibernate.teacher_student (student_id, teacher_id) values (?, ?)
Hibernate: insert into hibernate.teacher_student (teacher_id, student_id) values (?, ?)
Hibernate: insert into hibernate.teacher_student (teacher_id, student_id) values (?, ?)
为了避免这一现象,就需要某一方放弃维护teacher_student表的权限。如student放弃维护这一关系,使用inverse="true",如下:
<hibernate-mapping>
<class name="com.ligang.domain.Student" table="student">
<id name="id" column="id" type="long">
<generator class="identity"/>
</id>
<property name="name" column="name" type="string"/>
<set name="teachers" table="teacher_student" inverse="true">
<key column="student_id"></key>
<many-to-many class="com.ligang.domain.Teacher" column="teacher_id"></many-to-many>
</set>
</class>
</hibernate-mapping>
此时再按照上述方法增添就只有teacher去维护teacher_student表了,不会造成重复。
再看下多对多关联关系的查询:
@Test
public void getTeacher(){
Session session=hibernateDao.getSession();
Transaction tx=session.beginTransaction();
Teacher t=(Teacher) session.get(Teacher.class,3L);
System.out.println(t.getName());
System.out.println(t.getStudents().size());
tx.commit();
session.close();
}
这里同样存在这查询策略问题,此时Teacher类的映射文件对应的set标签的lazy属性有三个值,一个true、false、extra。默认为true,即实行延迟加载的策略,用到Student时才回去加载它,如下sql:
Hibernate: select teacher0_.id as id1_3_0_, teacher0_.name as name2_3_0_ from hibernate.teacher teacher0_ where teacher0_.id=?
teacher2
Hibernate: select students0_.teacher_id as teacher_1_3_0_, students0_.student_id as student_2_4_0_, student1_.id as id1_2_1_, student1_.name as name2_2_1_ from hibernate.teacher_student students0_ inner join hibernate.student student1_ on students0_.student_id=student1_.id where students0_.teacher_id=?
2
若设置为false,则表示在加载Teacher时立即去加载相关的Student,如下sql:
Hibernate: select teacher0_.id as id1_3_0_, teacher0_.name as name2_3_0_ from hibernate.teacher teacher0_ where teacher0_.id=?
Hibernate: select students0_.teacher_id as teacher_1_3_0_, students0_.student_id as student_2_4_0_, student1_.id as id1_2_1_, student1_.name as name2_2_1_ from hibernate.teacher_student students0_ inner join hibernate.student student1_ on students0_.student_id=student1_.id where students0_.teacher_id=?
teacher2
2
若设置为extra,则会更加智能化一些,即上述t.getStudents().size()并没有去访问Student的实际内容,仅仅是想获取数量,所以sql语句如下:
Hibernate: select teacher0_.id as id1_3_0_, teacher0_.name as name2_3_0_ from hibernate.teacher teacher0_ where teacher0_.id=?
teacher2
Hibernate: select count(student_id) from hibernate.teacher_student where teacher_id =?
2
再看下更新Teacher:
@Test
public void updateTeacher(){
Session session=hibernateDao.getSession();
Transaction tx=session.beginTransaction();
Teacher t=(Teacher) session.get(Teacher.class,6L);
Student s1=new Student();
s1.setName("assa");
Student s2=new Student();
s2.setName("sdfvdv");
Set<Student> students=new HashSet<Student>();
students.add(s1);
students.add(s2);
t.setStudents(students);
session.save(s1);
session.save(s2);
tx.commit();
session.close();
}
更新的时候,会先删除之前的teacher_student表中的相关记录,然后再新增新的记录,如下sql:
Hibernate: select teacher0_.id as id1_3_0_, teacher0_.name as name2_3_0_ from hibernate.teacher teacher0_ where teacher0_.id=?
Hibernate: insert into hibernate.student (name) values (?)
Hibernate: insert into hibernate.student (name) values (?)
Hibernate: delete from hibernate.teacher_student where teacher_id=?
Hibernate: insert into hibernate.teacher_student (teacher_id, student_id) values (?, ?)
Hibernate: insert into hibernate.teacher_student (teacher_id, student_id) values (?, ?)
若想转载请注明出处:
http://lgbolgger.iteye.com/blog/2125014
作者:iteye的乒乓狂魔
分享到:
相关推荐
“Hibernate 一对多,多对一,一对多双向关联”是指在Java持久化框架Hibernate中,实体间常见的三种关联关系。在数据库设计中,这种关联关系是常见的,例如一个用户可以有多个订单(一对多),一个订单对应一个用户...
本教程聚焦于Hibernate中的单向一对多关联映射,这是一个常见的实体关系模型,广泛应用于各种业务场景。 在数据库设计中,一对多关系意味着一个父表记录可以与多个子表记录相关联。例如,一个学生可以有多个课程,...
### Hibernate关联关系(一对多) #### 一、概念与背景 在软件开发中,尤其是在数据库设计及ORM(对象关系映射)技术的应用中,“一对多”关系是非常常见的一种数据关联方式。例如,一个班级可以拥有多个学生,但每...
这个标签表明此项目是在MyEclipse环境中创建和运行的,可能包含了一系列的源代码、配置文件、数据库脚本等,旨在展示如何在实际开发中应用Hibernate的多对多关系。 【压缩包子文件的文件名称列表】:Hibernate 多对...
Hibernate支持一对一、一对多、多对一、多对多等各种关系映射,通过注解或XML配置文件定义。例如,一个用户可以有多个订单,订单也可以属于一个用户: ```java @Entity @Table(name = "Order") public class Order ...
在Java世界中,Hibernate...通过这个双向多对多关系的教程,你可以深入了解Hibernate如何处理复杂的数据关联,并能灵活地在Java应用中进行数据库操作。记得在实践中不断探索,理解和掌握ORM框架的精髓,提升开发效率。
### Hibernate多表联合查询详解 #### 一、引言 在实际项目开发中,我们经常需要处理复杂的数据库查询,特别是涉及到多个表之间的关联查询。...希望本文能对你理解Hibernate的多表联合查询有所帮助。
除了上述特性,Hibernate-Extensions还提供了其他实用功能,如批量操作支持、动态实体、多对多关联的级联操作等。批量操作可以大大提高数据库操作的效率,动态实体则允许在运行时动态创建和操作实体类,多对多关联的...
总的来说,这个"Hibernate 系列教程 单表操作"将引导你掌握使用Hibernate进行数据库操作的基本技巧,并为更复杂的多表关联和高级功能打下坚实基础。通过实际操作,你将能够更好地理解和运用Hibernate,提高开发效率...
在关系数据库中,多对一和一对多关系是最常见的关联关系。Hibernate通过`@ManyToOne`和`@OneToMany`注解支持这两种关系的映射,使得实体之间的关联能够以直观的方式表示出来。 #### 双向关联与inverse设定 在实体...
8. **关联映射**:Hibernate支持一对一、一对多、多对一、多对多等各种关联关系的映射,方便地处理复杂的数据库关系。 9. **事件监听器**:通过事件监听机制,开发者可以在特定操作(如对象的保存、更新或删除)...
在Hibernate中,`inverse`属性是一个关键的概念,它用于定义一对多或多对一关系中的维护端。`inverse="true"`表示另一端负责维护关联关系,这在处理关联实体的保存和更新时具有重要意义。例如,如果你有一个学生类和...
7. **关联映射**:包括一对一(@OneToOne)、一对多(@OneToMany)、多对一(@ManyToOne)、多对多(@ManyToMany)关系的映射,方便处理对象间的关联关系。 8. **延迟加载**:Hibernate的懒加载策略可以在需要时才...
根据给定的文件内容,我们可以总结出一系列与Hibernate框架相关的知识点。这些知识点涵盖了常见的面试问题,可以帮助准备面试或深入理解Hibernate技术的人士更好地掌握该领域的内容。 ### Hibernate的检索方式 1. ...
2. **关联映射**:Hibernate支持多种关系映射,包括一对一(One-to-One)、一对多(One-to-Many)、多对一(Many-to-One)和多对多(Many-to-Many)。这部分可能详细解释了这些关系的配置,以及在Java对象和数据库表...
6. @ManyToOne、@OneToOne、@OneToMany、@ManyToMany:定义不同类型的关联关系,如一对一、一对多、多对多。 7. @JoinColumn:用于关联关系中指定外键字段的属性。 8. @Temporal:用于日期时间类型的字段,支持...
Hibernate支持多种关联关系映射,如一对一(OneToOne)、一对多(OneToMany)、多对一(ManyToOne)、多对多(ManyToMany)。关联映射需要在实体类和映射文件中进行详细配置。 九、懒加载与立即加载 懒加载(Lazy ...
Hibernate支持多种关联类型,包括一对一(@OneToOne)、一对多(@OneToMany)、多对一(@ManyToOne)和多对多(@ManyToMany)。通过这些关联,我们可以轻松处理复杂的对象关系。 总结 Hibernate 3.3作为一款成熟且...
4. **实体类与表映射**:学习如何使用Hibernate注解或XML配置文件将Java类映射到数据库表,包括主键生成策略、字段映射、关联映射(一对一、一对多、多对一、多对多)等。 5. **Session与Transaction**:Hibernate...