持久化类:Classes 班级,一个班级有多个学生,通过集合来建立关系
private Long cid; //标示符属性
private String name; //一般属性
private String description;
private Set<Student> students; //关联对象
持久化类:Student 学生
public class Student implements Serializable{
private Long sid;
private String name;
private String description;
private Classes classes;//关联对象 映射文件:Classes.hbm.xml 这里建立的student表中的外键cid,作用是:指的是通过class联系student拼接的sql语句,class.getStudents()
<hibernate-mapping>
<class name="com.itheima12.hibernate.domain.Classes" lazy="false">
<cache usage="read-write"/>
<id name="cid" length="5">
<generator class="increment"></generator>
</id>
<property name="description" length="50"></property>
<property name="name" length="20"></property>
<!--
set元素针对的就是Classes类中的Set属性
cascade 级联操作
null 默认值
save-update
在保存classes对象的时候,针对student进行保存或者更新的操作
在更新classes对象的时候,针对student进行保存或者更新的操作
all
delete
inverse 关系操作
default:classes维护classes与student之间的关系
true: classes不维护classes与student之间的关系
false: classes维护classes与student之间的关系
-->
<set name="students" cascade="save-update" inverse="true" lazy="extra">
<cache usage="read-write"/>
<!--
外键
告诉hibernate,通过cid就可以建立classes与student之间的关联
-->
<key>
<column name="cid"></column>
</key>
<!--
告诉hibernate,Classes类中的set集合中存放的是哪个元素
-->
<one-to-many class="com.itheima12.hibernate.domain.Student"/>
</set>
</class>
</hibernate-mapping>
映射文件:Student.hbm.xml(相比单项,这里指定了student与classes 类是many-to-one的关系) 上面已经指定student表中的外键,为什么这里还需要指定? 这里指定外键,是为了通过学生联系班级,student.getClasses(),在这里因为它是双向的,比如通过班级找学生,就要看班级的映射文件 , 通过学生找班级,就要看学生的映射文件,在学生的映射文件中有了外键,就可以之间利用外键拼接sql查询班级的sql语句 这里再次指定student表的外键,不影响表的结构,这里这么做,方便hibernate客户端通过学生操作班级。即:通过保存学生(多的一方),级联保存班级,但是注意sql语句是怎么执行
<hibernate-mapping>
<class name="com.itheima12.hibernate.domain.Student">
<id name="sid" length="5">
<generator class="increment"></generator>
</id>
<property name="description" length="50"></property>
<property name="name" length="20"></property>
<!--
外键
column
-->
<many-to-one name="classes" column="cid" class="com.itheima12.hibernate.domain.Classes"cascade="save-update"></many-to-one>
</class>
</hibernate-mapping>
客户端的操作 对于在多的方级联保存一的一方,虽然先保存学生,数据库把提供外键的classess先插入数据库, 而通过班级保存学生最后是通过update学生表的形式,最后把外键更新到学生表里面
/**hibernate输出的sql语句
* Hibernate:
select max(sid) from Student
Hibernate:
select max(cid) from Classes
Hibernate:
insert into Classes (description, name, cid) values(?, ?, ?)
Hibernate:
外键直接插入进去了(session.save保存的对象,发出的sql语句越少,越适合关系维护)
insert into Student (description, name,cid, sid) values (?, ?, ?, ?) */
@Test
public void testSaveStudent_Cascade_Save_Classes(){
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
Student student = new Student();
student.setName("asfd");
Classes classes = new Classes();
classes.setName("12期");
//创建班级与学生之间的关联
student.setClasses(classes); //通过学生建立的关联
session.save(student);
transaction.commit();
session.close();
}
操作两张表,并把数据保存到数据库中
在相应的类的映射文件设置级联保存的情况下,客户端(service层)该如何做? 关联对象 1、通过保存学生(多),级联保存班级 注意:根据hibernate打印的sql语句,即便session.save(student),还是先insert的是Classes,因为它提供student外键 客户端建立关联,把一个班级对象放入到自己类的属性private Classes classes;//关联对象 2、通过保存班级(一),级联保存学生 把已有的学生对象加入到Classes的 private Set<Student> students; //关联对象