首先,上圖...
上面的是hibernate中經(jīng)常用到的知識(shí)點(diǎn),我們一個(gè)一個(gè)看.
一 工作流程
- 讀取并解析配置文件
- 讀取并解析映射信息,創(chuàng)建SessionFactory
- 打開(kāi)Sesssion
- 創(chuàng)建事務(wù)Transation
- 持久化操作
- 提交事務(wù)
- 關(guān)閉Session
- 關(guān)閉SesstionFactory
jdbc 流程:
- 加載驅(qū)動(dòng)mysql
- 獲取連接
- 預(yù)編譯
- 執(zhí)行sql
- 將數(shù)據(jù)存入結(jié)果集
- 關(guān)閉數(shù)據(jù)庫(kù)
jdbc和hibernate區(qū)別:
jdbc優(yōu)點(diǎn):
SQL應(yīng)用靈活
數(shù)據(jù)庫(kù)移植
jdbc缺點(diǎn):
不便于維 代碼繁瑣 護(hù) 效率低
hibernate 框架 優(yōu)點(diǎn):
真正基于ORM模型
脫離java代碼 降低耦合度
操作簡(jiǎn)單,易用
缺點(diǎn):
不便于操作表結(jié)構(gòu)復(fù)雜的sql
不便于數(shù)據(jù)庫(kù)移植(跨數(shù)據(jù)庫(kù)移植)
代替了jdbc技術(shù),是一個(gè)全封裝的框架,不便于調(diào)試bug
什么時(shí)候用hibernate框架
表數(shù)量少 結(jié)構(gòu)不復(fù)雜,快速應(yīng)用它來(lái)開(kāi)發(fā)
hibernate中的緩存技術(shù):
1.只是一次連接數(shù)據(jù)庫(kù),多次使用
- 數(shù)據(jù)是存在緩存區(qū)里的,操作:session.get() session.save(),session.delete().
3.分為二級(jí)緩存:
一級(jí)緩存:session 存在 內(nèi)存的緩存區(qū)中
清理一級(jí)緩存的方式:
clear() 方法清理緩存直接從硬盤中的數(shù)據(jù)庫(kù)讀取
evict(對(duì)象) 執(zhí)行的是數(shù)據(jù)庫(kù)中的查詢,第一次查詢會(huì)失效
二級(jí)緩存:sessionFactort 存在 硬盤中
Hibernate 緩存執(zhí)行順序
當(dāng) Hibernate 根據(jù) ID 訪問(wèn)數(shù)據(jù)對(duì)象時(shí),首先會(huì)從一級(jí)緩存 Session 中查找。若查 不到且配置了二級(jí)緩存呢蛤,則會(huì)從二級(jí).
緩存中查找庄吼;若還查不到,就會(huì)查詢數(shù)據(jù)庫(kù)脯宿,把結(jié) 果按照 ID 放入到緩存中话告。執(zhí)行增兼搏、刪、改操作時(shí)沙郭,會(huì)同步更新緩存向族。
二級(jí)緩存內(nèi)容分類
根據(jù)緩存內(nèi)容的不同,可以將 Hibernate 二級(jí)緩存分為三類: (1)類緩存:緩存對(duì)象為實(shí)體類對(duì)象 (2)集合緩存:緩存對(duì)象為集合類對(duì)象 (3)查詢緩存:緩存對(duì)象為查詢結(jié)果
hibernate框架中g(shù)et方法和load方法獲取對(duì)象的方式有什么不同:
get和load方法都是根據(jù)id去獲得對(duì)應(yīng)數(shù)據(jù)的棠绘,但是獲得機(jī)制不同:如果使用get方法,hibernate會(huì)去確認(rèn)該id對(duì)應(yīng)的數(shù)據(jù)是否存在再扭,它首先會(huì)去session中去查詢(session緩存其實(shí)就hibernate的一級(jí)緩存)氧苍,如果沒(méi)有,再去二級(jí)緩存中去查詢泛范,如果再?zèng)]有让虐,就去數(shù)據(jù)庫(kù)中查詢,仍然沒(méi)有找到的話罢荡,就返回null
而使用load方法的話赡突,hibernate會(huì)認(rèn)定該id對(duì)應(yīng)的數(shù)據(jù)一定存在,它也會(huì)先去session緩存中去查找区赵,如果沒(méi)有找到惭缰,hibernate會(huì)根據(jù)lazy屬性值來(lái)確定是否使用延遲加載。如果lazy=‘true’ 笼才,就使用延遲加載漱受,返回該代理對(duì)象,等到真正訪問(wèn)到該對(duì)象的屬性時(shí)才會(huì)去二級(jí)緩存中查詢骡送,如果沒(méi)有昂羡,再去數(shù)據(jù)庫(kù)中查詢絮记,如果還沒(méi)有,就拋出org.hibernate.ObjectNotFoundException異常虐先。如果lazy='false' 則不使用延遲加載怨愤,這是load的訪問(wèn)機(jī)制就和get一樣了。
事物的特性:
1.原子性(不許分割)
2.一致性(兩個(gè)事物可以有添加和減少)
3.隔離性(兩個(gè)事物在執(zhí)行過(guò)程中,相互不影響)
4.持久性: (兩個(gè)事物執(zhí)行完畢后,影響一直有效)
hibernate對(duì)象的狀態(tài)
1.對(duì)象的臨時(shí)狀態(tài) Emp e = new Emp("hah", 1000.0, 21, date);
2.對(duì)象的持久化狀態(tài) session.save(e);
st.commit();
3.對(duì)象的游離狀態(tài)session.close();
事物是連接java代碼和數(shù)據(jù)庫(kù)的橋梁
hibernate框架中表之間的關(guān)系:
一對(duì)多
hibernate中級(jí)聯(lián)刪除:更改級(jí)聯(lián)關(guān)系為 cascade="delect";
刪除班級(jí),刪除學(xué)生 有外鍵
直接刪除:班級(jí)信息置為null 學(xué)生信息不變
:更改級(jí)聯(lián)關(guān)系為 cascade="delect" 根據(jù)外鍵,刪除當(dāng)前表及其有關(guān)系的其他表,刪除有外鍵有關(guān)系的表
一對(duì)多
在進(jìn)行解除關(guān)系或者刪除的時(shí)候 One-to-many比較簡(jiǎn)單,執(zhí)行的效率高 其他操作的時(shí)候many_to-one效率高
One-to-many 類和集合的關(guān)系
many-to-one 類和對(duì)象的關(guān)系
多對(duì)一(雙向)
以Student-classes表為例 一個(gè)班級(jí)有更多學(xué)生同樣更多學(xué)生在一個(gè)班級(jí)
建立 Student 和Classes的實(shí)體類
//Classes表中的屬性 注意學(xué)生集合
private Integer c_id;
private String c_name;
private Set<Student> stus;
//student表中的屬性
private Integer s_id;
private String s_name;
//建立關(guān)系: 多個(gè)學(xué)生 一個(gè)班級(jí)
private Classes cls;
//classes表的映射文件
<hibernate-mapping>
<class name="cn.lanou3g.vo.Classes" >
<id name="c_id">
<generator class="increment" />
</id>
<property name="c_name"/>
<!-- 搭建一對(duì)多的關(guān)系 inverse是否維系關(guān)系 默認(rèn)false
cascade 級(jí)聯(lián)關(guān)系 save-update 保存或更新的時(shí)候維系關(guān)系
delete 級(jí)聯(lián)刪除-->
<set name="stus" inverse="false" cascade="save-update">
<!--從表的外鍵 -->
<key column="c_id"></key>
<!-- 指定對(duì)應(yīng)關(guān)系 它是stus對(duì)應(yīng)的實(shí)體類-->
<one-to-many class="cn.lanou3g.vo.Student"/>
</set>
</class>
</hibernate-mapping>
//Student的映射文件
<hibernate-mapping>
<class name="cn.lanou3g.vo.Student">
<id name="s_id">
<generator class="increment"/>
</id>
<property name="s_name"/>
<!-- 建立關(guān)系 cls 多對(duì)一 cascade 級(jí)聯(lián)關(guān)系-->
<many-to-one name="cls" class="cn.lanou3g.vo.Classes" cascade="save-update">
<!-- 這里的外鍵,要與one-to-many對(duì)應(yīng)的外鍵一致 -->
<!-- column 指定從表的外鍵-->
<column name="c_id"></column>
</many-to-one>
</class>
</hibernate-mapping>
public class TextCon {
Session session=HibernateSessionFactory.getSession();
Transaction ts=session.beginTransaction();
@Test
public void textConn(){
//新建配置對(duì)象 目的是自動(dòng)加載配置文件
Configuration cfg = new Configuration();
cfg.configure();//自動(dòng)加載主配置文件
//開(kāi)啟session工廠
SessionFactory sf=cfg.buildSessionFactory();
}
//保存學(xué)生 保存班級(jí)
//@Test
public void textaddStuandcls(){
//新增班級(jí)
Student stu = new Student();
stu.setS_name("momo");
//新增班級(jí)
Classes cls = new Classes();
cls.setC_name("java");
//通過(guò)學(xué)生保存班級(jí)
stu.setCls(cls);
session.save(stu);
ts.commit();
}
//更新學(xué)生 級(jí)聯(lián)保存班級(jí)
//@Test
public void textupdateStuandcls(){
Student stu = (Student)session.get(Student.class, 1);
stu.setS_name("lida");
session.save(stu);
ts.commit();
}
//給學(xué)生賦班級(jí)
//@Test
public void testUpdateStu(){
Student stu = (Student)session.get(Student.class, 2);
Classes cls = (Classes)session.get(Classes.class, 1);
stu.setCls(cls);
session.save(stu);
ts.commit();
}
//解除一個(gè)班級(jí)和所有學(xué)生之間的關(guān)系(注意保存班級(jí))
// delect() 兩表都刪除
//update 外鍵為null
@Test
public void testdelStuandcla(){
Classes cls = (Classes)session.get(Classes.class, 1);
//Student stu = (Student)session.get(Student.class, 1);
//cls.setStus(null);//級(jí)聯(lián)關(guān)系改為null
session.update(cls);
ts.commit();
}
}
多對(duì)多:
以course-student表為例 很多課程被很多學(xué)生選擇
//student表中的屬性
private Integer s_id;
private String s_name;
private Set<Course> cours;
//coutse表中的屬性
private Integer c_id;
private String c_name;
//建立聯(lián)系 多對(duì)多 多個(gè)課程被多了學(xué)生選擇
private Set<Student> stus;
//Course表中映射文件
<hibernate-mapping>
<class name="cn.lanou3g.vo.Student">
<id name="s_id">
<generator class="increment"/>
</id>
<property name="s_name"/>
<!-- 建立關(guān)系 cls 多對(duì)一 cascade 級(jí)聯(lián)關(guān)系-->
<set name="cours" table="student_course" cascade="all">
<key column="s_id"/>
<many-to-many class="cn.lanou3g.vo.Course" column="c_id"/>
</set>
</class>
</hibernate-mapping>
//student的映射文件
<hibernate-mapping>
<class name="cn.lanou3g.vo.Course">
<id name="c_id">
<generator class="increment"/>
</id>
<property name="c_name"/>
<!-- 建立關(guān)系 cls 多對(duì)一 cascade 級(jí)聯(lián)關(guān)系-->
<set name="stus" table="student_course" cascade="all">
<key column="c_id"/>
<many-to-many class="cn.lanou3g.vo.Student" column="s_id"/>
</set>
</class>
</hibernate-mapping>
public class TextCon {
Session session=HibernateSessionFactory.getSession();
Transaction ts=session.beginTransaction();
@Test
public void textConn(){
Configuration cfg = new Configuration();
cfg.configure();
SessionFactory sf = cfg.buildSessionFactory();
}
//添加一個(gè)新課程 添加一個(gè)新學(xué)生
//先保存主表 在保存從表
//@Test
public void textinsert(){
Student stu = new Student();
Course cours =new Course();
stu.setS_name("box");
cours.setC_name("java");
Set<Student> stus = new HashSet<Student>();
stus.add(stu);
cours.setStus(stus);
session.save(cours);
ts.commit();
}
//獲取學(xué)生 修改學(xué)生姓名 課程中添加修改后的學(xué)生姓名
//@Test
public void textUpdatestu(){
Student stu = (Student)session.get(Student.class, 1);
stu.setS_name("燦烈");
Course cours = (Course)session.get(Course.class, 1);
Set<Student> stus = new HashSet<Student>();
stus.add(stu);
cours.setStus(stus);
session.save(cours);
ts.commit();
}
//解除課程1和所有學(xué)生的關(guān)系
//解除課程1和所欲學(xué)生之間的關(guān)系
//多對(duì)多關(guān)系的刪除,只影響中間表,其他關(guān)聯(lián)表不動(dòng)
//設(shè)置學(xué)生為null
//@Test
public void textdel(){
Course cours = (Course)session.get(Course.class, 1);
cours.setStus(null);
session.save(cours);
ts.commit();
}
//刪除課程1下編號(hào)為1 的人
//解除一個(gè)學(xué)生和一個(gè)課程的關(guān)系(值刪除中間表)
//多對(duì)多中單條刪除用集合中的remove()進(jìn)行刪除
@Test
public void textdelmid(){
Course cours = (Course)session.get(Course.class, 2);
Student stu = (Student)session.get(Student.class, 2);
Set<Course> c = stu.getCours();
c.remove(cours);
session.save(cours);
ts.commit();
}
}
一對(duì)一
以person-card為例 一個(gè)人只有一個(gè)身份證
//card的屬性
private Integer c_id;
private String c_name;
private Person c_p;
//person的屬性
private Integer p_id;//主鍵
private String p_name;
private Card p_c;
//card的映射文件
<hibernate-mapping>
<!-- 引入實(shí)體類的全類名 -->
<class name="cn.lanou3g.entity.Card">
<!-- 主鍵字段 -->
<id name="c_id">
<generator class="increment"/>
</id>
<!--普通字段 -->
<property name="c_name"/>
<!-- 直接指定對(duì)應(yīng)關(guān)系
name 在當(dāng)前類中存在的類類型
class name屬性對(duì)應(yīng)的全類型
cascade 對(duì)當(dāng)前表的操作crud
constrained="false"代表當(dāng)前表是主表-->
<one-to-one name="c_p" class="cn.lanou3g.entity.Person" cascade="all" constrained="true"/>
</class>
//Person的映射文件
<hibernate-mapping>
<!-- 引入實(shí)體類的全類名 -->
<class name="cn.lanou3g.entity.Person">
<!-- 主鍵字段 -->
<id name="p_id">
<generator class="increment"/>
</id>
<!--普通字段 -->
<property name="p_name"/>
<!-- 直接指定對(duì)應(yīng)關(guān)系
name 在當(dāng)前類中存在的類類型
class name屬性對(duì)應(yīng)的全類型
cascade 對(duì)當(dāng)前表的操作crud
constrained="false"代表當(dāng)前表是主表
true 代表從表-->
<one-to-one name="p_c" class="cn.lanou3g.entity.Card" cascade="all" constrained="false"/>
</class>
</hibernate-mapping>
public class text {
Session session = HibernateSessionFactory.getSession();
Transaction ts=session.beginTransaction();
//自動(dòng)建表
@Test
public void textConn(){
//新建配置對(duì)象 目的是自動(dòng)加載配置文件
Configuration cfg = new Configuration();
cfg.configure();//自動(dòng)加載主配置文件
//開(kāi)啟session工廠
SessionFactory sf=cfg.buildSessionFactory();
}
// 同時(shí)添加人(主表)和身份證
// @Test
public void textInser(){
Person p = new Person("梁靖");
Card c = new Card("152727199603111025");
//先保存從表中的關(guān)聯(lián)字段
c.setC_p(p);
// p.setP_c(c);
//保存從表
session.save(c);
ts.commit();
}
//修改id為1的姓名
// @Test
public void textUpdate(){
Person p = (Person)session.get(Person.class, 2);
p.setP_name("梁敏");
session.save(p);
ts.commit();
}
//刪除用戶 刪除身份證 從主表中刪除 從表的也刪除
//思路:通過(guò)主表獲取關(guān)聯(lián)字段
//關(guān)聯(lián)字段放入主表
// 刪除主表
// @Test
public void textdelect(){
Person p = (Person)session.get(Person.class, 2);
// Card p_c =p.getP_c();
// p.setP_c(p_c);
session.delete(p);
ts.commit();
}
}
懶加載
映射文件中加入屬性lazy="true"
為什么用它:
防止內(nèi)存溢出,遞歸調(diào)出方法
- 解決:
1.去掉任何一方的toString()
2.在不需要查詢的一方的配置文件中加入lazy="true"
HQL語(yǔ)句:
- 是指hibernate sql
- 查詢?nèi)?/li>
- 查詢某一個(gè)字段
- 按條件查詢0
//分頁(yè)
Query q = session.createQuery("from User");
//起始位置
q.setFirstResult(0);
//一次展示多少條
q.setMaxResults(5);
//把查詢到的結(jié)果放入list集合
List list = q.list();
System.out.println(list);//遍歷并且輸出集合