0.0 參數(shù)
class.catalog="指定數(shù)據(jù)庫的鞋喇,建議刪掉"
set.inverse:是否要放棄維護外鍵關(guān)系
true: 放棄維護主鍵
false: 我
default value:false
set.cascade:是否需要級聯(lián)操作 (5個)
save-update:A保存侦香,同時保存B
delete:刪除A鄙皇,同時刪除B伴逸,AB都不存在
delete-orphan:孤兒刪除,解除關(guān)系颓芭,同時將B刪除亡问,A存在的州藕。
如果需要配置多項酝陈,使用逗號分隔沉帮。<set cascade="save-update,delete">
all : save-update 和 delete 整合
all-delete-orphan : 三個整合
? 容器<set> 提供兩個屬性:fetch穆壕、lazy
fetch:確定使用sql格式
lazy:關(guān)聯(lián)對象是否延遲喇勋。
? fetch:join、select压彭、subselect
join:底層使用迫切左外連接
select:使用多個select語句(默認(rèn)值)
subselect:使用子查詢
? lazy:false、true皱碘、extra
false:立即
true:延遲(默認(rèn)值)
extra:極其懶惰
1.0 簡單多對多(雙向多對多)
<hibernate-mapping package="cc.sirius.bean">
<class name="對應(yīng)類名" table="表名">
<id name="主鍵">
<generator class="主鍵生成策略"></generator>
</id>
<property name="類對象的對應(yīng)屬性"></property>
<set name="對應(yīng)set屬性" table="維護關(guān)聯(lián)關(guān)系的表名">
<key column="在維護關(guān)系那里的自己的主鍵"></key>
<many-to-many class="關(guān)聯(lián)類" column="關(guān)聯(lián)類的關(guān)聯(lián)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("數(shù)學(xué)");
// 維護關(guān)系
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=數(shù)學(xué)]]
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
這里必須先把中間維護關(guān)系的表給更改了才行
@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 調(diào)用上面的add函數(shù)
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
(?, ?)
這里并不在中間表做關(guān)系維護,直白一點都办,就是說Student已經(jīng)不關(guān)心Course了势木,所以如果通過把Course 添加到Student的set里歌懒,并不能維護關(guān)系及皂。
反過來验烧,這里用course 添加student就可以維護關(guān)系噪窘,hibernate依然會在數(shù)據(jù)庫中通過中間表來維護關(guān)系倔监。
@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("數(shù)學(xué)");
// 維護關(guān)系
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刪除洽蛀,中間表的關(guān)系不會刪除郊供,通過Student得到Course并且施加更新驮审,不會生效疯淫。
既然你放棄了她熙掺,你給的東西咕宿,再好她也不要。
勉強得到的载城,不過是幻夢诉瓦。(通過Student得到Course睬澡,修改并不會寫入)
2.2 更新和刪除
調(diào)用上面的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=?
如果中間表有關(guān)系煞聪,也就是數(shù)據(jù)是通過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級聯(lián)加載
3.1Student放棄維護Course云稚,并且級聯(lián)加載Course
不愛了静陈,為什么還藕斷絲連地關(guān)心鲸拥。
<!--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("數(shù)學(xué)");
// 維護關(guān)系
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級聯(lián)了course,而course并沒有級聯(lián)student;
可以想象沛申,這里的查詢應(yīng)該可以成功
@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());//沒辦法找到铁材,這里
}
結(jié)果卻是:
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默認(rèn)為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典徘,他放棄了維護外鍵,但是配置了級聯(lián)刪除
@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
- 在關(guān)聯(lián)表中把和student選過的課全刪了(這里不是只刪除student-course那些行)
- 然后在course中刪除student學(xué)過的所有課程
- 最后才是刪除student
4.0 Student放棄維護Course,并且雙方都級聯(lián)加載對方
他主動放棄淑掌,雙方卻還牽掛著彼此
為了效果明顯抛腕,這里懶加載都關(guān)掉
4.1 級聯(lián)插入
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("數(shù)學(xué)");
// 維護關(guān)系
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 級聯(lián)更新
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對應(yīng)所有course
- 一直查找,直到course和student之間不再有關(guān)聯(lián)
- 然后先刪除中間表
- 再刪除兩個表的數(shù)據(jù)
- 結(jié)局是兩個表的數(shù)據(jù)基本全廢了刹悴,等于清表