Session概述:
Session接口是hibernate向應(yīng)用程序提供的操作數(shù)據(jù)庫(kù)的主要接口 它提供基本的保存 更新 刪除 加載 java對(duì)象的方法
Session具有一個(gè)緩存腻惠,位于緩存中的對(duì)象稱(chēng)之為持久化對(duì)象韭寸,它和數(shù)據(jù)庫(kù)中的相關(guān)記錄對(duì)應(yīng)妹萨;Session 能夠在某些時(shí)間點(diǎn)按照緩存對(duì)象的變化來(lái)執(zhí)行相關(guān)的SQL語(yǔ)句
站在持久化的角度虱颗,hibernate把對(duì)象分為4種狀態(tài):持久化狀態(tài) 臨時(shí)狀態(tài) 游離狀態(tài) 刪除狀態(tài); Session的特定方法能使對(duì)象從一個(gè)狀態(tài)轉(zhuǎn)換到另一個(gè)狀態(tài)
持久化對(duì)象的狀態(tài)
臨時(shí)對(duì)象:在使用代理主鍵情況下盯仪,OID通常為NULL 套硼;不處于Session緩存中;在數(shù)據(jù)庫(kù)中沒(méi)有對(duì)應(yīng)的記錄蛆橡;
持久化對(duì)象:OID通常不為NULL,位于Session緩存中掘譬,和數(shù)據(jù)庫(kù)相關(guān)的記錄對(duì)應(yīng)泰演,flush()緩存時(shí),會(huì)根據(jù)持久化對(duì)象屬性的變化同步更新數(shù)據(jù)庫(kù)
在同一個(gè)session實(shí)例緩存中葱轩,數(shù)據(jù)庫(kù)表中的每一條記錄只對(duì)應(yīng)唯一的持久化對(duì)象
刪除對(duì)象:數(shù)據(jù)庫(kù)沒(méi)有OID記錄睦焕,不再session緩存中,一般情況下靴拱。應(yīng)用程序不該使用被刪除的對(duì)象
游離對(duì)象:OID通常不為NULL垃喊,不再session緩存中,一般情況下游離對(duì)象是從持久化對(duì)象轉(zhuǎn)變過(guò)來(lái)的缭嫡,以此在數(shù)據(jù)庫(kù)中可能還存在與他對(duì)應(yīng)的記錄
Session緩存:只要Session實(shí)例沒(méi)有結(jié)束生命周期并且不清理緩存缔御,緩存對(duì)對(duì)象引用一直持有,減少對(duì)數(shù)據(jù)庫(kù)的操作頻率
/**
* Session緩存 只要Session實(shí)例沒(méi)有結(jié)束生命周期并且不再清理緩存妇蛀,緩存對(duì)對(duì)象引用一直持有耕突,減少對(duì)數(shù)據(jù)庫(kù)的操作頻率
*
* Session對(duì)緩存操作:
* flush():使數(shù)據(jù)庫(kù)記錄于緩存中的對(duì)象保持一致,為了保持一致可能會(huì)放送對(duì)應(yīng)的SQL
* refresh(): 強(qiáng)制放送SELECT語(yǔ)句 使緩存的對(duì)象和數(shù)據(jù)庫(kù)中保持一致(一定會(huì)發(fā))
* clear():清理緩存
*
*/
public static void testSessionCache() {
StandardServiceRegistry registry = new StandardServiceRegistryBuilder().configure().build();// 配置文件configure()
SessionFactory sessionFactory = new MetadataSources(registry).buildMetadata().buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
// 第一次查詢(xún)
News news = (News) session.get(News.class, 1);// 并放入緩存
System.out.println(news.toString());
// 第二次查詢(xún) 檢查是否緩存 沒(méi)有緩存才去查數(shù)據(jù)庫(kù)
News news2 = (News) session.get(News.class, 1);// 不會(huì)查詢(xún)數(shù)據(jù)庫(kù)
System.out.println(news2.toString());
transaction.commit();
session.close();
sessionFactory.close();
}
- 方法中進(jìn)行了兩次查詢(xún)但只會(huì)查詢(xún)一次數(shù)據(jù)
Session對(duì)緩存操作:
- flush():使數(shù)據(jù)庫(kù)記錄于緩存中的對(duì)象保持一致评架,為了保持一致可能會(huì)放送對(duì)應(yīng)的SQL
- refresh(): 強(qiáng)制發(fā)送SELECT語(yǔ)句 使緩存的對(duì)象和數(shù)據(jù)庫(kù)中保持一致(一定會(huì)發(fā))
- clear():清理緩存
Session緩存flush():數(shù)據(jù)庫(kù)記錄于緩存中的對(duì)象保持一致
transaction.commit()方法中先調(diào)用Session的flush()方法 在提交事務(wù)
flush()的方法可能會(huì)放送SQL眷茁,但不會(huì)提交事務(wù)
注意:在未提交事務(wù)或顯示調(diào)用flush()方法之前,也有可能進(jìn)行flush()操作
1).執(zhí)行HQL 或QBC查詢(xún)纵诞,會(huì)先f(wàn)lush()操作上祈,已得到數(shù)據(jù)表最新記錄
2).若記錄的ID是由底層數(shù)據(jù)庫(kù)自增方式生成的,則在調(diào)用save()方法后浙芙,會(huì)立即放送INSER語(yǔ)句登刺,應(yīng)為sava方法必須保證對(duì)象ID是存在的
/**
*
* Session緩存flush()
*
*
* 1.transaction.commit()方法中向調(diào)用Session的flush()方法 在提交事務(wù)
* 2.flush()的方法可能會(huì)放送SQL,但不會(huì)提交事務(wù)
* 3.注意:在未提交事務(wù)或顯示調(diào)用flush()方法之前嗡呼,也有可能進(jìn)行flush()操作
* 1).執(zhí)行HQL 或QBC查詢(xún)纸俭,會(huì)先f(wàn)lush()操作,已得到數(shù)據(jù)表最新記錄
* 2).若記錄的ID是由底層數(shù)據(jù)庫(kù)自增方式生成的南窗,則在調(diào)用save()方法后揍很,會(huì)立即放送INSER語(yǔ)句,應(yīng)為sava方法
* 必須保證對(duì)象ID是存在的
*/
public static void testSessionFlush() {
StandardServiceRegistry registry = new StandardServiceRegistryBuilder().configure().build();// 配置文件configure()
SessionFactory sessionFactory = new MetadataSources(registry).buildMetadata().buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
News news = (News) session.get(News.class, 1);
news.setTitle("下雨了");
transaction.commit();
session.close();
sessionFactory.close();
}
Session緩存refresh(): 使緩存的對(duì)象和數(shù)據(jù)庫(kù)中保持一致
/**
* Session緩存refresh()
* 但可能數(shù)據(jù)不會(huì)最新(數(shù)據(jù)庫(kù)的隔離級(jí)別)mysql(默認(rèn)REPEATABLE READ)
* */
public static void testSessionRefresh() {
StandardServiceRegistry registry = new StandardServiceRegistryBuilder().configure().build();// 配置文件configure()
SessionFactory sessionFactory = new MetadataSources(registry).buildMetadata().buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
News news = (News) session.get(News.class, 1);
System.out.println(news.toString());
session.refresh(news);//刷新緩存
System.out.println(news.toString());
transaction.commit();
session.close();
sessionFactory.close();
}
會(huì)受到數(shù)據(jù)庫(kù)隔離級(jí)別的限制
數(shù)據(jù)庫(kù)的隔離級(jí)別
串行化(SERIALIZABLE):所有事務(wù)都一個(gè)接一個(gè)地串行執(zhí)行万伤,這樣可以避免幻讀
可重復(fù)讀(REPEATABLE READ):所有被Select獲取的數(shù)據(jù)都不能被修改窒悔,這樣就可以避免一個(gè)事務(wù)前后讀取數(shù)據(jù)不一致的情況
讀已提交(READ COMMITED):被讀取的數(shù)據(jù)可以被其他事務(wù)修改。這樣就可能導(dǎo)致不可重復(fù)讀
讀未提交(READ UNCOMMITED):這是最低的隔離等級(jí)敌买,允許其他事務(wù)看到?jīng)]有提交的數(shù)據(jù)简珠。這種等級(jí)會(huì)導(dǎo)致臟讀
save()方法:對(duì)象保存到數(shù)據(jù)庫(kù)
- 1.使一個(gè)臨時(shí)對(duì)象變?yōu)槌志没瘜?duì)象
- 2.為對(duì)象分配id
- 3.在flush緩存使會(huì)放送insert語(yǔ)句
- 4.在save之前的id使無(wú)效的
- 5.持久化對(duì)象id不能修改
/**
* save()方法
* 1.使一個(gè)臨時(shí)對(duì)象變?yōu)槌志没瘜?duì)象
* 2.為對(duì)象分配id
* 3.在flush緩存使會(huì)放送insert語(yǔ)句
* 4.在save之前的id使無(wú)效的
* 5.持久化對(duì)象id不能修改
* */
public static void testSave() {
StandardServiceRegistry registry = new StandardServiceRegistryBuilder().configure().build();// 配置文件configure()
SessionFactory sessionFactory = new MetadataSources(registry).buildMetadata().buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
News news = new News("成都早", "好好生活", new Date(new Date().getTime()));
session.save(news);
transaction.commit();
session.close();
sessionFactory.close();
}
persist()方法:也會(huì)執(zhí)行insert語(yǔ)句 在對(duì)象已經(jīng)有id了,則不會(huì)執(zhí)行insert語(yǔ)句虹钮,而拋出異常
/**
* persist()方法
* persist也會(huì)執(zhí)行insert語(yǔ)句 在對(duì)象已經(jīng)有id了北救,則不會(huì)執(zhí)行insert語(yǔ)句荐操,而拋出異常
* */
public static void testPersist() {
StandardServiceRegistry registry = new StandardServiceRegistryBuilder().configure().build();// 配置文件configure()
SessionFactory sessionFactory = new MetadataSources(registry).buildMetadata().buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
News news = new News("長(zhǎng)沙的測(cè)試早", "行啊是從下沙生活", new Date(new Date().getTime()));
session.persist(news);
transaction.commit();
session.close();
sessionFactory.close();
}
get()方法:根據(jù)OID回去數(shù)據(jù)庫(kù)數(shù)據(jù)返回對(duì)象
/**
* get()方法
* */
public static void testGet() {
StandardServiceRegistry registry = new StandardServiceRegistryBuilder().configure().build();// 配置文件configure()
SessionFactory sessionFactory = new MetadataSources(registry).buildMetadata().buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
News news = (News) session.get(News.class, 2);
System.out.println(news.toString());
transaction.commit();
session.close();
sessionFactory.close();
}
load()方法:根據(jù)OID回去數(shù)據(jù)庫(kù)數(shù)據(jù)返回代理對(duì)象
- 與get()方法區(qū)別:
1.get方法會(huì)立即加載對(duì)象 load方法若不使用該對(duì)象湾揽,則不會(huì)立即加載對(duì)象森瘪,返回一個(gè)代理對(duì)象
2.若數(shù)據(jù)庫(kù)沒(méi)有對(duì)應(yīng)記錄 get返回null load 不使用沒(méi)有問(wèn)題 使用拋出異常
3.load 方法可能拋出LazyInitializationException異常:在需要初始化代理對(duì)象關(guān)閉了session
/**
* load()方法
*
* 與get()方法區(qū)別
*
* 1.get方法會(huì)立即加載對(duì)象 load方法若不使用該對(duì)象,則不會(huì)立即加載對(duì)象尖殃,返回一個(gè)代理對(duì)象
* 2.若數(shù)據(jù)庫(kù)沒(méi)有對(duì)應(yīng)記錄 get返回null load 不使用沒(méi)有問(wèn)題 使用拋出異常
* 3.load 方法可能拋出LazyInitializationException異常:在需要初始化代理對(duì)象關(guān)閉了session
* */
public static void testLoad() {
StandardServiceRegistry registry = new StandardServiceRegistryBuilder().configure().build();// 配置文件configure()
SessionFactory sessionFactory = new MetadataSources(registry).buildMetadata().buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
News news = (News) session.load(News.class, 2);
System.out.println(news.toString());
transaction.commit();
session.close();
sessionFactory.close();
}
update()方法:強(qiáng)制使數(shù)據(jù)庫(kù)記錄于對(duì)象保持一致
1.若更新一個(gè)持久化對(duì)象不需要調(diào)用update方法攘宙,應(yīng)為在調(diào)用commit()方法時(shí)屯耸,會(huì)先執(zhí)行flush方法
2.更新一個(gè)游離對(duì)象 需要顯示調(diào)用session的update方法,可以把游離對(duì)象變?yōu)槌志没瘜?duì)象
3.無(wú)論要更新的游離對(duì)象是否和數(shù)據(jù)庫(kù)一致蹭劈,都會(huì)發(fā)送SQL語(yǔ)句
4.不讓update順便的發(fā)送語(yǔ)句 在.hbm.xml文件的class節(jié)點(diǎn)設(shè)置 select-before-update="true"他會(huì)先查詢(xún)疗绣,一般不會(huì)設(shè)置除非和觸發(fā)器結(jié)合
5.數(shù)據(jù)庫(kù)沒(méi)有該對(duì)象,會(huì)拋出異常
6.關(guān)聯(lián)一個(gè)游離對(duì)象時(shí)铺韧,如果session緩存中有同一個(gè)OID的持久化對(duì)象會(huì)拋出異常多矮,因在session緩存中不能有同一個(gè)OID對(duì)象
/**
* update()方法
* 1.若更細(xì)一個(gè)持久化對(duì)象不需要調(diào)用update方法,應(yīng)為在調(diào)用commit()方法時(shí)哈打,會(huì)先執(zhí)行flush方法
* 2.更新一個(gè)游離對(duì)象 需要顯示調(diào)用session的update方法塔逃,可以把游離對(duì)象變?yōu)槌志没瘜?duì)象
* 3.無(wú)論要更新的游離對(duì)象是否和數(shù)據(jù)庫(kù)一致,都會(huì)發(fā)送SQL語(yǔ)句
* 4.不讓update順便的發(fā)送語(yǔ)句 在.hbm.xml文件的class節(jié)點(diǎn)設(shè)置 select-before-update="true"他會(huì)先查詢(xún)料仗,一般不會(huì)設(shè)置除非和觸發(fā)器結(jié)合
* 5.數(shù)據(jù)庫(kù)沒(méi)有該對(duì)象湾盗,會(huì)拋出異常
* 6.關(guān)聯(lián)一個(gè)游離對(duì)象時(shí),如果session緩存中有同一個(gè)OID的持久化對(duì)象會(huì)拋出異常立轧,因在session緩存中不能有同一個(gè)OID對(duì)象
* */
public static void testUpdate() {
StandardServiceRegistry registry = new StandardServiceRegistryBuilder().configure().build();// 配置文件configure()
SessionFactory sessionFactory = new MetadataSources(registry).buildMetadata().buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
News news = (News) session.get(News.class, 2);
System.out.println(news.toString());
news.setTitle("xasxsaxsax");
session.update(news);
transaction.commit();
session.close();
sessionFactory.close();
}
saveOrUpdate()方法: OID為空?qǐng)?zhí)行insert語(yǔ)句 OID不為空記錄存在執(zhí)行update語(yǔ)句
- 若OID不為空 數(shù)據(jù)庫(kù)中沒(méi)有對(duì)應(yīng)記錄 會(huì)拋出異常
/**
* saveOrUpdate()方法 OID為空?qǐng)?zhí)行insert語(yǔ)句 OID不為空記錄存在執(zhí)行update語(yǔ)句
* 1.若OID不為空 數(shù)據(jù)庫(kù)中沒(méi)有對(duì)應(yīng)記錄 會(huì)拋出異常
* */
public static void testSaveOrUpdate() {
StandardServiceRegistry registry = new StandardServiceRegistryBuilder().configure().build();// 配置文件configure()
SessionFactory sessionFactory = new MetadataSources(registry).buildMetadata().buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
News news = new News("長(zhǎng)沙的測(cè)試早", "行啊是從下沙生活", new Date(new Date().getTime()));
session.saveOrUpdate(news);
transaction.commit();
session.close();
sessionFactory.close();
}
delete()方法:刪除數(shù)據(jù)庫(kù)對(duì)應(yīng)數(shù)據(jù)
- 只要ODI對(duì)應(yīng)記錄存在 刪除 沒(méi)有記錄拋出異常 (不分對(duì)象狀態(tài) 只和OID有關(guān))
- 可以通過(guò)設(shè)置hibernate配置 <property name="use_identifier_rollback">true</property> 把刪除的對(duì)象OID變成null
/**
* delete()方法 只要ODI對(duì)應(yīng)記錄存在 刪除 沒(méi)有記錄拋出異常 (不分對(duì)象狀態(tài) 只和OID有關(guān))
*
* 可以通過(guò)設(shè)置hibernate配置 <property name="use_identifier_rollback">true</property> OID變成null
* */
public static void testDelete() {
StandardServiceRegistry registry = new StandardServiceRegistryBuilder().configure().build();// 配置文件configure()
SessionFactory sessionFactory = new MetadataSources(registry).buildMetadata().buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
News news = new News("長(zhǎng)沙的測(cè)試早", "行啊是從下沙生活", new Date(new Date().getTime()));
news.setId(1);
session.delete(news);
transaction.commit();
session.close();
sessionFactory.close();
}
evict()方法:從緩沖中移除指定的持久化對(duì)象
/**
* evict()從緩沖中移除指定的持久化對(duì)象
* */
public static void testEvict() {
StandardServiceRegistry registry = new StandardServiceRegistryBuilder().configure().build();// 配置文件configure()
SessionFactory sessionFactory = new MetadataSources(registry).buildMetadata().buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
News news = (News) session.get(News.class, 2);
News news1 = (News) session.get(News.class, 3);
news.setTitle("cdxscxsacxs");
news1.setTitle("cdxscxsacxs");
session.evict(news1);
transaction.commit();
session.close();
sessionFactory.close();
}
doWork()方法:使用原生SQL
/**
* doWork()方法
* 調(diào)用數(shù)據(jù)庫(kù)原生的Connection對(duì)先
* */
public static void testDoWork() {
StandardServiceRegistry registry = new StandardServiceRegistryBuilder().configure().build();// 配置文件configure()
SessionFactory sessionFactory = new MetadataSources(registry).buildMetadata().buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
session.doWork(new Work() {
@Override
public void execute(Connection arg0) throws SQLException {
System.out.println(arg0);
//原生sql
}
});
transaction.commit();
session.close();
sessionFactory.close();
}
dynamic-insert="true" 只修改改變的數(shù)據(jù)表類(lèi) 性能降低
/**
*dynamic-insert="true" 只修改改變的 性能降低
* */
public static void testDynamic() {
StandardServiceRegistry registry = new StandardServiceRegistryBuilder().configure().build();// 配置文件configure()
SessionFactory sessionFactory = new MetadataSources(registry).buildMetadata().buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
News news = (News) session.get(News.class, 2);
news.setAuthor("1111111");
transaction.commit();
session.close();
sessionFactory.close();
}