Hibernate多对多配置
程序员文章站
2022-04-24 14:26:12
...
场景:
Student和Course,每一个Student有多个Course,每一个Course也有多个Student。
类文件如下:
配置文件:
生成SQL代码:
[color=gray]Hibernate: drop table student_course cascade constraints
Hibernate: drop table test_course cascade constraints
Hibernate: drop table test_student cascade constraints
Hibernate: create table student_course (student_id number(10,0) not null, course_id number(10,0) not null, primary key (course_id, student_id))
Hibernate: create table test_course (id number(10,0) not null, name varchar2(255 char), primary key (id))
Hibernate: create table test_student (id number(10,0) not null, name varchar2(255 char), primary key (id))
Hibernate: alter table student_course add constraint FK_8eu2c4tg0i8amuwx6n6d4i8h0 foreign key (course_id) references test_course
Hibernate: alter table student_course add constraint FK_3shg469d7jsf2a81b5x62jlq1 foreign key (student_id) references test_student[/color]
[size=x-large][b]插入[/b][/size]
运行之后会执行:
[color=gray]Hibernate: select course_.id, course_.name as name2_1_ from test_course course_ where course_.id=?
Hibernate: select course_.id, course_.name as name2_1_ from test_course course_ where course_.id=?
Hibernate: insert into test_student (name, id) values (?, ?)
Hibernate: insert into test_course (name, id) values (?, ?)
Hibernate: insert into test_student (name, id) values (?, ?)
Hibernate: insert into test_course (name, id) values (?, ?)
Hibernate: insert into student_course (student_id, course_id) values (?, ?)
Hibernate: insert into student_course (student_id, course_id) values (?, ?)
Hibernate: insert into student_course (student_id, course_id) values (?, ?)
[/color]
结果为:
[img]http://dl2.iteye.com/upload/attachment/0091/4050/c1be5cb4-1174-3ca0-98fa-b01f62d1145b.jpg[/img]
[size=x-large][b]修改[/b][/size]
修改的时候要注意<set>元素中的inverse属性.
inverse表示是否由对方来维持中间表。
更详细的说明在:
[url]http://www.cnblogs.com/mabaishui/archive/2009/10/19/1585843.html[/url]
这里假如我们设置Student的<set>的inverse为true, 那么当我们使用
student.setCourses(c1,c2)
这样的代码, 是不能对student_course表产生作用的。
也就是说Student不能对many-to-many关联表产生作用。
只有Course才可以。
[b]inverse=true相当于使该对象放弃了对关联表的操作功能。many-to-many默认下inverse=false,相当于双方都可以对关联表进行维护操作[/b]
-如果两边都设置为true, 那这个关联表student_course就永远不会得到任何相关操作。
[size=x-large][b]查询[/b][/size]
这里查询id为2的学生的所有课程名称。
该查询执行SQL语句为:
[color=gray]Hibernate: select student0_.id as id1_2_0_, student0_.name as name2_2_0_ from test_student student0_ where student0_.id=?
Hibernate: select courses0_.student_id as student1_2_1_, courses0_.course_id as course2_0_1_, course1_.id as id1_1_0_, course1_.name as name2_1_0_ from student_course courses0_ inner join test_course course1_ on courses0_.course_id=course1_.id where courses0_.student_id=?[/color]
第二条是inner join语句, 整理一下就是:
select sc.student_id as student1, sc.course_id as course1, tc.id as tc_id, tc.name as tc_name from student_course sc inner join test_course tc on sc.course_id=tc.id where sc.student_id=?
由于Hibernate的SQL别名起的有点乱, 我就改了一下。
上面的语句中, student_course ->sc
test_course ->tc
也就是说, Hibernate对关联表和Course表进行了join查询。
最终从Course表获取所有包含关联表student_course中所包含的查询学生的id所对应的Course.
[b](student_course表中查询该学生id的row->获取对应的course_id->到course表中查询对应id的row)[/b]
Student和Course,每一个Student有多个Course,每一个Course也有多个Student。
类文件如下:
public class Student
{
private int id;
private String name;
private Set<Course> courses;
}
public class Course
{
private int id;
private String name;
private Set<Student> students;
}
配置文件:
<hibernate-mapping package="many2many">
<class name="Student" table="test_student">
<id name="id" column="id" type="int">
<generator class="assigned">
</generator>
</id>
<property name="name" column="name" type="string" />
<!-- table是连接表的名字
对于多对多,cascade一定不能设置all,而是要设置save-update.
比如我们要删除某个学生,单并不代表要删除该学生的课程。-->
<set name="courses" table="student_course" cascade="save-update">
<!-- 这里的column是指与Student所关联的表的外键 -->
<key column="student_id">
</key>
<many-to-many class="Course" column="course_id"/>
</set>
</class>
</hibernate-mapping>
<hibernate-mapping package="many2many">
<class name="Course" table="test_course">
<id name="id" column="id" type="int">
<generator class="assigned">
</generator>
</id>
<property name="name" column="name" type="string" />
<!-- table=student_course是两个Entity的关联表,用于负责多对多关联
Hibernate会在数据库生成表student_course,对应的Course的外键是下面配置
的course_id
-->
<set name="students" table="student_course" cascade="save-update">
<key>
<column name="course_id"/>
</key>
<!-- 这里如果不加入column=course_id,就会生成一个包含elt列的表。 -->
<!-- 这里student_id表示对应的student的外键 -->
<many-to-many class="Student" column="student_id"/>
</set>
</class>
</hibernate-mapping>
生成SQL代码:
[color=gray]Hibernate: drop table student_course cascade constraints
Hibernate: drop table test_course cascade constraints
Hibernate: drop table test_student cascade constraints
Hibernate: create table student_course (student_id number(10,0) not null, course_id number(10,0) not null, primary key (course_id, student_id))
Hibernate: create table test_course (id number(10,0) not null, name varchar2(255 char), primary key (id))
Hibernate: create table test_student (id number(10,0) not null, name varchar2(255 char), primary key (id))
Hibernate: alter table student_course add constraint FK_8eu2c4tg0i8amuwx6n6d4i8h0 foreign key (course_id) references test_course
Hibernate: alter table student_course add constraint FK_3shg469d7jsf2a81b5x62jlq1 foreign key (student_id) references test_student[/color]
[size=x-large][b]插入[/b][/size]
Session session=HibernateUtil.openSession();
Transaction tx=session.beginTransaction();
Student s1=new Student(1, "alleni", null);
Student s2=new Student(2,"eline",null);
Course c1=new Course(1,"English",null);
Course c2=new Course(2,"Draw",null);
s1.setCourses(ArraysHelper.asSet(c1));
s2.setCourses(ArraysHelper.asSet(c1,c2));
session.save(s1);
session.save(s2);
tx.commit();
运行之后会执行:
[color=gray]Hibernate: select course_.id, course_.name as name2_1_ from test_course course_ where course_.id=?
Hibernate: select course_.id, course_.name as name2_1_ from test_course course_ where course_.id=?
Hibernate: insert into test_student (name, id) values (?, ?)
Hibernate: insert into test_course (name, id) values (?, ?)
Hibernate: insert into test_student (name, id) values (?, ?)
Hibernate: insert into test_course (name, id) values (?, ?)
Hibernate: insert into student_course (student_id, course_id) values (?, ?)
Hibernate: insert into student_course (student_id, course_id) values (?, ?)
Hibernate: insert into student_course (student_id, course_id) values (?, ?)
[/color]
结果为:
[img]http://dl2.iteye.com/upload/attachment/0091/4050/c1be5cb4-1174-3ca0-98fa-b01f62d1145b.jpg[/img]
[size=x-large][b]修改[/b][/size]
修改的时候要注意<set>元素中的inverse属性.
inverse表示是否由对方来维持中间表。
更详细的说明在:
[url]http://www.cnblogs.com/mabaishui/archive/2009/10/19/1585843.html[/url]
这里假如我们设置Student的<set>的inverse为true, 那么当我们使用
student.setCourses(c1,c2)
这样的代码, 是不能对student_course表产生作用的。
也就是说Student不能对many-to-many关联表产生作用。
只有Course才可以。
[b]inverse=true相当于使该对象放弃了对关联表的操作功能。many-to-many默认下inverse=false,相当于双方都可以对关联表进行维护操作[/b]
-如果两边都设置为true, 那这个关联表student_course就永远不会得到任何相关操作。
Session session=HibernateUtil.openSession();
Transaction tx=session.beginTransaction();
Student s1=new Student(1, "alleni", null);
Student s2=new Student(2,"eline",null);
Course c1=new Course(1,"English",null);
Course c2=new Course(2,"Draw",null);
// s1.setCourses(ArraysHelper.asSet(c1));
// s2.setCourses(ArraysHelper.asSet(c1,c2));
// session.update(s1);
// session.update(s2);
// tx.commit();
//当Student.inverse=false,Course.inverse=true,使用如上操作。
c1.setStudents(ArraysHelper.asSet(s1,s2));
c2.setStudents(ArraysHelper.asSet(s2));
session.update(c1);
session.update(c2);
tx.commit();
//当Student.inverse=true,Course.inverse=false,使用如上操作.
//默认inverse都是false,所以默认情况下上面两种操作都可以。
[size=x-large][b]查询[/b][/size]
Session session=HibernateUtil.openSession();
Student s=(Student) session.load(Student.class, 2);
for(Course c:s.getCourses()){
System.out.println(c.getName());
}
这里查询id为2的学生的所有课程名称。
该查询执行SQL语句为:
[color=gray]Hibernate: select student0_.id as id1_2_0_, student0_.name as name2_2_0_ from test_student student0_ where student0_.id=?
Hibernate: select courses0_.student_id as student1_2_1_, courses0_.course_id as course2_0_1_, course1_.id as id1_1_0_, course1_.name as name2_1_0_ from student_course courses0_ inner join test_course course1_ on courses0_.course_id=course1_.id where courses0_.student_id=?[/color]
第二条是inner join语句, 整理一下就是:
select sc.student_id as student1, sc.course_id as course1, tc.id as tc_id, tc.name as tc_name from student_course sc inner join test_course tc on sc.course_id=tc.id where sc.student_id=?
由于Hibernate的SQL别名起的有点乱, 我就改了一下。
上面的语句中, student_course ->sc
test_course ->tc
也就是说, Hibernate对关联表和Course表进行了join查询。
最终从Course表获取所有包含关联表student_course中所包含的查询学生的id所对应的Course.
[b](student_course表中查询该学生id的row->获取对应的course_id->到course表中查询对应id的row)[/b]
上一篇: script标签什么意思
下一篇: 指定网卡发送数据包