hibernate最终还是在最底层生成sql语句来操作数据库
一对多的单项:
实例:班级中有多个学生,班级能找到学生,班级中放入一个集合装学生,学生不能找到班级
持久化类:Classes 班级,一个班级有多个学生,通过集合来建立关系
- public class Classes implements Serializable{
private Long cid; //标示符属性
private String name; //一般属性
private String description;
private Set<Student> students; //关联对象
持久化类:Student 学生
映射文件:Classes.hbm.xml
该映射配置文件中重点注意set属性,该属性主要是针对Classes类中的Set集合属性,在映射配置文件中指定这个属性
外键:就是在Classes.hbm.xml的配置文件中指定一个属性作为student表中的外键,即:在student表中增加一个表字段(列)cid
外键的作用:告诉hibernate怎么样生成sql语句,另外获得查询Classes的时候,同时要获得学生信息,代码怎么实现?
指定类与类之间的联系,告诉hibernate客户端Classes联系的是那个Student,告诉hibernate,Classes类中的set集合中存放的是哪个元素
因为hibernate出现前还没出现泛型
<one-to-many class="com.itheima12.hibernate.domain.Student"/>
<hibernate-mapping>
<class name="com.itheima12.hibernate.domain.Classes">
<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">
<!--
外键
告诉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>
映射文件:Classes.hbm.xml
<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>
</class>
</hibernate-mapping>
客户端的操作:保存Classes的同时保存学生,注意:通过session只保存了Classes,保存student是hibernate内部保存,称为隐式保存
为什么student也能够保存?
我们在Classes.hbm.xml中set元素中建立两个类的联系时候,设置了级联操作cascade="save-update"
save-update
在保存classes对象的时候,针对student进行保存或者更新的操作
在更新classes对象的时候,针对student进行保存或者更新的操作
方式二:可以不设置级联操作,先保存Classes,获取cid,new student(),把cid
/**
* 在保存班级的时候,级联保存学生
*/
@Test
public void testSaveClasses_Cascade_Save_Student(){
Session session = sessionFactory.getCurrentSession();
Transaction transaction = session.beginTransaction();
Classes classes = new Classes();
classes.setName("黑马视频班");
classes.setDescription("野牛");
Student student = new Student();
student.setName("班秘");
student.setDescription("凤姐");
//建立classes与student之间的关联
Set<Student> students = new HashSet<Student>();
students.add(student);
classes.setStudents(students);
session.save(classes); //显示保存,把保存student称为隐式保存
transaction.commit();
}
hibernate产生的sql语句
注意:对于保存一的一方级联保存多的情况,下面insert sql语句,两张表的基本数据插入插入数据库,外键并没有在插入student表数据的时候插入数据库中,而后面通过更新update Student
表,把cid外键放入Student表中
如果在一对多双向,通过保存多的一方student级联保存Classes,不需要后面的update,直接将外键cid插入student表中,少了条sql语句,所以说保存学生,即:一对多的双向关联,保存多的一方,在多的一方维护关系更好
hibernate出现时候还没泛型,如果hibernate没有告诉的话,Classes联系哪个Student
hibernate报的一个错误
一个对象引用(references)没有保存的临时状态的实例,在flushing之前保存一个临时状态的对象
错误解析:transient短暂的,临时的·
在flushing之前,保存一个临时状态的对象
原因:这是在Classes.hbm.xml文件中set元素中去掉 cascade="save-update"
在客户端建立Classes与Student建立关系,意思是保存Classes的同时也要保存Student
所以hibernate在保存classes的时候,就不知道该怎么办了。
inverse属性
inverse指的是关系操作,针对的就是外键
inverse 关系操作
default:classes维护classes与student之间的关系
true: classes不维护classes与student之间的关系
false: classes维护classes与student之间的关系
当上面在Classes.hbm.xml文件中set元素中设置inverse=true,那么保存Classes 和student时候,Student表中没有外键cid的值
如果在Classes.hbm.xml文件中,inverse没有写,默认classes维护classes与student之间的关系
所以发出了更新关系的update语句
update
Student
set
cid=?
where
sid=? 这句语句是产生Student中的外键cid的值,inverse为default/false
怎样同时操作两张表,同时把数据保存到数据库中
重点注意:映射文件设置级联的情况,必须在客户端建立两个类之间的关联,比如:保存classes的时候同时保存student,就要把student添加到Classes这个类的set集合属性中
1、对于一对多的数据保存在班级一方的映射文件的set元素中 cascade="save-update" 级联保存和更新, 注意级联并不维护外键,即不会为学生表保存外键值,外键需要inverse=“false”维护
在客户端的代码
2、