0.0 参数
class.catalog="指定数据库的,建议删掉"
set.inverse:是否要放弃维护外键关系
true: 放弃维护主键
false: 我
default value:false
set.cascade:是否需要级联操作 (5个)
save-update:A保存,同时保存B
delete:删除A,同时删除B,AB都不存在
delete-orphan:孤儿删除,解除关系,同时将B删除,A存在的。
如果需要配置多项,使用逗号分隔。<set cascade="save-update,delete">
all : save-update 和 delete 整合
all-delete-orphan : 三个整合
容器<set> 提供两个属性:fetch、lazy
fetch:确定使用sql格式
lazy:关联对象是否延迟。
fetch:join、select、subselect
join:底层使用迫切左外连接
select:使用多个select语句(默认值)
subselect:使用子查询
lazy:false、true、extra
false:立即
true:延迟(默认值)
extra:极其懒惰
1.0 简单多对多(双向多对多)
<hibernate-mapping package="cc.sirius.bean">
<class name="对应类名" table="表名">
<id name="主键">
<generator class="主键生成策略"></generator>
</id>
<property name="类对象的对应属性"></property>
<set name="对应set属性" table="维护关联关系的表名">
<key column="在维护关系那里的自己的主键"></key>
<many-to-many class="关联类" column="关联类的关联id"></many-to-many>
</set>
</class>
</hibernate-mapping>
<?xml version="1.0" encoding="UTF-8"?>
<!-- Student.hbm.xml -->
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="cc.sirius.bean">
<class name="Student" table="t_student" >
<id name="sid" column="sid">
<generator class="native"></generator>
</id>
<property name="name"></property>
<property name="sex"></property>
<set name="courses" table="t_student_course" >
<key column="sid" not-null="true" ></key>
<many-to-many class="Course" column="cid" ></many-to-many>
</set>
</class>
</hibernate-mapping>
<?xml version="1.0" encoding="UTF-8"?>
<!-- Course.hbm.xml -->
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="cc.sirius.bean">
<class name="Course" table="t_course">
<id name="cid" column="cid">
<generator class="native"></generator>
</id>
<property name="cname"></property>
<set name="students" table="t_student_course" >
<key column="cid" not-null="true"></key>
<many-to-many class="Student" column="sid"></many-to-many>
</set>
</class>
</hibernate-mapping>
1.1添加
@Test
public void add() {
Session session = HibernateUtils.openSession();
session.beginTransaction();
// -----------------------------------------------------
Student s1 = new Student();
s1.setName("旺旺");
s1.setSex("男");
Student s2 = new Student();
s2.setName("小董");
s2.setSex("男");
Course c1 = new Course();
c1.setCname("语文");
Course c2 = new Course();
c2.setCname("数学");
// 维护关系
s1.getCourses().add(c1);
s1.getCourses().add(c2);
s2.getCourses().add(c1);
s2.getCourses().add(c2);
session.save(c1);
session.save(c2);
session.save(s1);
session.save(s2);
// ------------------------------------------------------
session.getTransaction().commit();
session.close();
}
输出:
Hibernate:
insert
into
t_course
(cname)
values
(?)
Hibernate:
insert
into
t_course
(cname)
values
(?)
Hibernate:
insert
into
t_student
(name, sex)
values
(?, ?)
Hibernate:
insert
into
t_student
(name, sex)
values
(?, ?)
Hibernate:
insert
into
t_student_course
(sid, cid)
values
(?, ?)
Hibernate:
insert
into
t_student_course
(sid, cid)
values
(?, ?)
Hibernate:
insert
into
t_student_course
(sid, cid)
values
(?, ?)
Hibernate:
insert
into
t_student_course
(sid, cid)
values
(?, ?)
1.2 更新
@Test
public void update() {
Session session = HibernateUtils.openSession();
session.beginTransaction();
// -----------------------------------------------------
Student student01 = (Student) session.get(Student.class, 1);
Iterator<Course> it = student01.getCourses().iterator();
int i=0;
while(it.hasNext()){
Course c = it.next();
c.setCname("小白"+i++);
}
// ------------------------------------------------------
session.getTransaction().commit();
session.close();
}
Hibernate:
select
student0_.sid as sid2_0_,
student0_.name as name2_0_,
student0_.sex as sex2_0_
from
t_student student0_
where
student0_.sid=?
Hibernate:
select
courses0_.sid as sid2_1_,
courses0_.cid as cid1_,
course1_.cid as cid0_0_,
course1_.cname as cname0_0_
from
t_student_course courses0_
inner join
t_course course1_
on courses0_.cid=course1_.cid
where
courses0_.sid=?
[Course [cid=1, cname=语文], Course [cid=2, cname=数学]]
1.3 删除
@Test
public void deleteOne(){
Session session = HibernateUtils.openSession();
session.beginTransaction();
// -----------------------------------------------------
session.createQuery("delete from Student where sid=1").executeUpdate();
// ------------------------------------------------------
session.getTransaction().commit();
session.close();
}
Hibernate:
delete
from
t_student
where
sid=1
10:46:16,083 WARN JDBCExceptionReporter:233 - SQL Error: 1451, SQLState: 23000
10:46:16,083 ERROR JDBCExceptionReporter:234 - Cannot delete or update a parent row: a foreign key constraint fails (`hbm_rele`.`t_student_course`, CONSTRAINT `FK3F2869CAEE65BEC0` FOREIGN KEY (`sid`) REFERENCES `t_student` (`sid`))
10:46:16,089 INFO SessionFactoryImpl:927 - closing
这里必须先把中间维护关系的表给更改了才行
@Test
public void deleteOneWithObj(){
Session session = HibernateUtils.openSession();
session.beginTransaction();
// -----------------------------------------------------
Student student = (Student) session.get(Student.class, 1);
session.delete(student);
// ------------------------------------------------------
session.getTransaction().commit();
session.close();
}
Hibernate:
select
student0_.sid as sid2_0_,
student0_.name as name2_0_,
student0_.sex as sex2_0_
from
t_student student0_
where
student0_.sid=?
Hibernate:
delete
from
t_student_course
where
sid=?
Hibernate:
delete
from
t_student
where
sid=?
2.0 一方放弃维护外键(单向多对多)
Student 放弃维护外键
<!--student-->
<set name="courses" table="t_student_course" inverse="true">
<key column="sid" not-null="true" ></key>
<many-to-many class="Course" column="cid" ></many-to-many>
</set>
`cid` int(11) NOT NULL,
`sid` int(11) NOT NULL,
PRIMARY KEY (`cid`,`sid`),
KEY `FK3F2869CAEE65BEC0` (`sid`),
KEY `FK3F2869CA4E48E42` (`cid`),
CONSTRAINT `FK3F2869CA4E48E42` FOREIGN KEY (`cid`) REFERENCES `t_course` (`cid
`),
CONSTRAINT `FK3F2869CAEE65BEC0` FOREIGN KEY (`sid`) REFERENCES `t_student` (`s
id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
2.1 调用上面的add函数
Hibernate:
insert
into
t_course
(cname)
values
(?)
Hibernate:
insert
into
t_course
(cname)
values
(?)
Hibernate:
insert
into
t_student
(name, sex)
values
(?, ?)
Hibernate:
insert
into
t_student
(name, sex)
values
(?, ?)
这里并不在中间表做关系维护,直白一点,就是说Student已经不关心Course了,所以如果通过把Course 添加到Student的set里,并不能维护关系。
反过来,这里用course 添加student就可以维护关系,hibernate依然会在数据库中通过中间表来维护关系。
@Test
public void addInverseFalse() {
Session session = HibernateUtils.openSession();
session.beginTransaction();
// -----------------------------------------------------
Student s1 = new Student();
s1.setName("旺旺");
s1.setSex("男");
Student s2 = new Student();
s2.setName("小董");
s2.setSex("男");
Course c1 = new Course();
c1.setCname("语文");
Course c2 = new Course();
c2.setCname("数学");
// 维护关系
c1.getStudents().add(s1);
c1.getStudents().add(s2);
c2.getStudents().add(s1);
c2.getStudents().add(s2);
session.save(c1);
session.save(c2);
session.save(s1);
session.save(s2);
// ------------------------------------------------------
session.getTransaction().commit();
// session.close();
}
Hibernate:
insert
into
t_course
(cname)
values
(?)
Hibernate:
insert
into
t_course
(cname)
values
(?)
Hibernate:
insert
into
t_student
(name, sex)
values
(?, ?)
Hibernate:
insert
into
t_student
(name, sex)
values
(?, ?)
Hibernate:
insert
into
t_student_course
(cid, sid)
values
(?, ?)
Hibernate:
insert
into
t_student_course
(cid, sid)
values
(?, ?)
Hibernate:
insert
into
t_student_course
(cid, sid)
values
(?, ?)
Hibernate:
insert
into
t_student_course
(cid, sid)
values
(?, ?)
所以,同理有:通过Student删除,中间表的关系不会删除,通过Student得到Course并且施加更新,不会生效。
既然你放弃了她,你给的东西,再好她也不要。
勉强得到的,不过是幻梦。(通过Student得到Course,修改并不会写入)
2.2 更新和删除
调用上面的update()
Hibernate:
select
student0_.sid as sid2_0_,
student0_.name as name2_0_,
student0_.sex as sex2_0_
from
t_student student0_
where
student0_.sid=?
Hibernate:
select
courses0_.sid as sid2_1_,
courses0_.cid as cid1_,
course1_.cid as cid0_0_,
course1_.cname as cname0_0_
from
t_student_course courses0_
inner join
t_course course1_
on courses0_.cid=course1_.cid
where
courses0_.sid=?
如果中间表有关系,也就是数据是通过Course维护的,deleteOne()
Hibernate:
delete
from
t_student
where
sid=2
11:16:53,179 WARN JDBCExceptionReporter:233 - SQL Error: 1451, SQLState: 23000
11:16:53,180 ERROR JDBCExceptionReporter:234 - Cannot delete or update a parent row: a foreign key constraint fails (`hbm_rele`.`t_student_course`, CONSTRAINT `FK3F2869CAEE65BEC0` FOREIGN KEY (`sid`) REFERENCES `t_student` (`sid`))
11:16:53,188 INFO SessionFactoryImpl:927 - closing
3.0级联加载
3.1Student放弃维护Course,并且级联加载Course
不爱了,为什么还藕断丝连地关心。
<!--student-->
<set name="courses" table="t_student_course" inverse="true" cascade="all">
<key column="sid" not-null="true" ></key>
<many-to-many class="Course" column="cid" ></many-to-many>
</set>
@Test
public void addInverseTrueCascadeAll() {
Session session = HibernateUtils.openSession();
session.beginTransaction();
// -----------------------------------------------------
Student s1 = new Student();
s1.setName("旺旺");
s1.setSex("男");
Student s2 = new Student();
s2.setName("小董");
s2.setSex("男");
Course c1 = new Course();
c1.setCname("语文");
Course c2 = new Course();
c2.setCname("数学");
// 维护关系
c1.getStudents().add(s1);
c1.getStudents().add(s2);
c2.getStudents().add(s1);
c2.getStudents().add(s2);
session.save(c1);
session.save(c2);
// ------------------------------------------------------
session.getTransaction().commit();
// session.close();
}
Hibernate:
insert
into
t_course
(cname)
values
(?)
Hibernate:
insert
into
t_course
(cname)
values
(?)
Hibernate:
insert
into
t_student_course
(cid, sid)
values
(?, ?)
//error
这里会出错,因为student放弃了维护,虽然student级联了course,而course并没有级联student;
可以想象,这里的查询应该可以成功
@Test
/*
* student
* Inverse: true
* Cascade: all
*/
public void findCascadeAll() {
Session session = HibernateUtils.openSession();
session.beginTransaction();
// -----------------------------------------------------
Student student01 = (Student) session.get(Student.class, 1);
// ------------------------------------------------------
session.getTransaction().commit();
session.close();
System.out.println(student01.getCourses());//没办法找到,这里
}
结果却是:
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: cc.sirius.bean.Student.courses, no session or session was closed
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:383)
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:375)
at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:368)
at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:111)
at org.hibernate.collection.PersistentSet.toString(PersistentSet.java:332)
at java.lang.String.valueOf(String.java:2994)
at java.io.PrintStream.println(PrintStream.java:821)
at cc.sirius.service.TestDo2.findCascadeAll(TestDo2.java:138)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at ...
这里是懒加载的问题,
set 的lazy默认为true。修改为false
<set name="courses" table="t_student_course" inverse="true" lazy="false" cascade="all">
<key column="sid" not-null="true" ></key>
<many-to-many class="Course" column="cid" ></many-to-many>
</set>
Hibernate:
select
student0_.sid as sid2_0_,
student0_.name as name2_0_,
student0_.sex as sex2_0_
from
t_student student0_
where
student0_.sid=?
Hibernate:
select
courses0_.sid as sid2_1_,
courses0_.cid as cid1_,
course1_.cid as cid0_0_,
course1_.cname as cname0_0_
from
t_student_course courses0_
inner join
t_course course1_
on courses0_.cid=course1_.cid
where
courses0_.sid=?
[]
3.2删除
至于删除,如果是student,他放弃了维护外键,但是配置了级联删除
@Test
public void deleteOneWithObj(){
Session session = HibernateUtils.openSession();
session.beginTransaction();
// -----------------------------------------------------
Student student = (Student) session.get(Student.class, 1);
session.delete(student);
// ------------------------------------------------------
session.getTransaction().commit();
session.close();
}
Hibernate:
select
student0_.sid as sid2_0_,
student0_.name as name2_0_,
student0_.sex as sex2_0_
from
t_student student0_
where
student0_.sid=?
Hibernate:
select
courses0_.sid as sid2_1_,
courses0_.cid as cid1_,
course1_.cid as cid0_0_,
course1_.cname as cname0_0_
from
t_student_course courses0_
inner join
t_course course1_
on courses0_.cid=course1_.cid
where
courses0_.sid=?
Hibernate:
delete
from
t_student_course
where
cid=?
Hibernate:
delete
from
t_student_course
where
cid=?
Hibernate:
delete
from
t_course
where
cid=?
Hibernate:
delete
from
t_course
where
cid=?
Hibernate:
delete
from
t_student
where
sid=?
- 删除student02的时候,先查找student02
- 查找student02的 course
- 在关联表中把和student选过的课全删了(这里不是只删除student-course那些行)
- 然后在course中删除student学过的所有课程
- 最后才是删除student
4.0 Student放弃维护Course,并且双方都级联加载对方
他主动放弃,双方却还牵挂着彼此
为了效果明显,这里懒加载都关掉
4.1 级联插入
public void addInverseTrueCascadeAll() {
Session session = HibernateUtils.openSession();
session.beginTransaction();
// -----------------------------------------------------
Student s1 = new Student();
s1.setName("旺旺");
s1.setSex("男");
Student s2 = new Student();
s2.setName("小董");
s2.setSex("男");
Course c1 = new Course();
c1.setCname("语文");
Course c2 = new Course();
c2.setCname("数学");
// 维护关系
c1.getStudents().add(s1);
c1.getStudents().add(s2);
c2.getStudents().add(s1);
c2.getStudents().add(s2);
session.save(c1);
session.save(c2);
// ------------------------------------------------------
session.getTransaction().commit();
session.close();
}
效果:
Hibernate:
insert
into
t_course
(cname)
values
(?)
Hibernate:
insert
into
t_student
(name, sex)
values
(?, ?)
Hibernate:
insert
into
t_student
(name, sex)
values
(?, ?)
Hibernate:
insert
into
t_course
(cname)
values
(?)
Hibernate:
insert
into
t_student_course
(cid, sid)
values
(?, ?)
Hibernate:
insert
into
t_student_course
(cid, sid)
values
(?, ?)
Hibernate:
insert
into
t_student_course
(cid, sid)
values
(?, ?)
Hibernate:
insert
into
t_student_course
(cid, sid)
values
(?, ?)
4.2 级联更新
public void updateCascadeAll() {
Session session = HibernateUtils.openSession();
session.beginTransaction();
// -----------------------------------------------------
Course course=(Course) session.get(Course.class,1);
Iterator<Student> it = course.getStudents().iterator();
while(it.hasNext()){
it.next().setName("灰太狼");
}
session.save(course);
// ------------------------------------------------------
session.getTransaction().commit();
session.close();
}
Hibernate:
select
course0_.cid as cid0_0_,
course0_.cname as cname0_0_
from
t_course course0_
where
course0_.cid=?
Hibernate:
select
students0_.cid as cid0_1_,
students0_.sid as sid1_,
student1_.sid as sid2_0_,
student1_.name as name2_0_,
student1_.sex as sex2_0_
from
t_student_course students0_
inner join
t_student student1_
on students0_.sid=student1_.sid
where
students0_.cid=?
Hibernate:
select
courses0_.sid as sid2_1_,
courses0_.cid as cid1_,
course1_.cid as cid0_0_,
course1_.cname as cname0_0_
from
t_student_course courses0_
inner join
t_course course1_
on courses0_.cid=course1_.cid
where
courses0_.sid=?
Hibernate:
select
students0_.cid as cid0_1_,
students0_.sid as sid1_,
student1_.sid as sid2_0_,
student1_.name as name2_0_,
student1_.sex as sex2_0_
from
t_student_course students0_
inner join
t_student student1_
on students0_.sid=student1_.sid
where
students0_.cid=?
Hibernate:
select
courses0_.sid as sid2_1_,
courses0_.cid as cid1_,
course1_.cid as cid0_0_,
course1_.cname as cname0_0_
from
t_student_course courses0_
inner join
t_course course1_
on courses0_.cid=course1_.cid
where
courses0_.sid=?
Hibernate:
update
t_student
set
name=?,
sex=?
where
sid=?
Hibernate:
update
t_student
set
name=?,
sex=?
where
sid=?
4.3 地狱级别的删除
@Test
public void deleteCourse(){
Session session = HibernateUtils.openSession();
session.beginTransaction();
// -----------------------------------------------------
Course course = (Course) session.get(Course.class, 1);
session.delete(course);
// ------------------------------------------------------
session.getTransaction().commit();
session.close();
}
Hibernate:
select
course0_.cid as cid0_0_,
course0_.cname as cname0_0_
from
t_course course0_
where
course0_.cid=?
Hibernate:
select
students0_.cid as cid0_1_,
students0_.sid as sid1_,
student1_.sid as sid2_0_,
student1_.name as name2_0_,
student1_.sex as sex2_0_
from
t_student_course students0_
inner join
t_student student1_
on students0_.sid=student1_.sid
where
students0_.cid=?
Hibernate:
select
courses0_.sid as sid2_1_,
courses0_.cid as cid1_,
course1_.cid as cid0_0_,
course1_.cname as cname0_0_
from
t_student_course courses0_
inner join
t_course course1_
on courses0_.cid=course1_.cid
where
courses0_.sid=?
Hibernate:
select
students0_.cid as cid0_1_,
students0_.sid as sid1_,
student1_.sid as sid2_0_,
student1_.name as name2_0_,
student1_.sex as sex2_0_
from
t_student_course students0_
inner join
t_student student1_
on students0_.sid=student1_.sid
where
students0_.cid=?
Hibernate:
select
courses0_.sid as sid2_1_,
courses0_.cid as cid1_,
course1_.cid as cid0_0_,
course1_.cname as cname0_0_
from
t_student_course courses0_
inner join
t_course course1_
on courses0_.cid=course1_.cid
where
courses0_.sid=?
Hibernate:
delete
from
t_student_course
where
cid=?
Hibernate:
delete
from
t_student_course
where
cid=?
Hibernate:
delete
from
t_student
where
sid=?
Hibernate:
delete
from
t_course
where
cid=?
Hibernate:
delete
from
t_student
where
sid=?
Hibernate:
delete
from
t_course
where
cid=?
- 查找course01
- 查找course01底下所有student
- 查找student对应所有course
- 一直查找,直到course和student之间不再有关联
- 然后先删除中间表
- 再删除两个表的数据
- 结局是两个表的数据基本全废了,等于清表