Session概述:
Session接口是hibernate向應用程序提供的操作數據庫的主要接口 它提供基本的保存 更新 刪除 加載 java對象的方法
Session具有一個緩存,位于緩存中的對象稱之為持久化對象,它和數據庫中的相關記錄對應;Session 能夠在某些時間點按照緩存對象的變化來執行相關的SQL語句
站在持久化的角度,hibernate把對象分為4種狀態:持久化狀態 臨時狀態 游離狀態 刪除狀態; Session的特定方法能使對象從一個狀態轉換到另一個狀態
持久化對象的狀態
臨時對象:在使用代理主鍵情況下,OID通常為NULL ;不處于Session緩存中;在數據庫中沒有對應的記錄;
持久化對象:OID通常不為NULL,位于Session緩存中,和數據庫相關的記錄對應,flush()緩存時,會根據持久化對象屬性的變化同步更新數據庫
在同一個session實例緩存中,數據庫表中的每一條記錄只對應唯一的持久化對象
刪除對象:數據庫沒有OID記錄,不再session緩存中,一般情況下。應用程序不該使用被刪除的對象
游離對象:OID通常不為NULL,不再session緩存中,一般情況下游離對象是從持久化對象轉變過來的,以此在數據庫中可能還存在與他對應的記錄
Session緩存:只要Session實例沒有結束生命周期并且不清理緩存,緩存對對象引用一直持有,減少對數據庫的操作頻率
/**
* Session緩存 只要Session實例沒有結束生命周期并且不再清理緩存,緩存對對象引用一直持有,減少對數據庫的操作頻率
*
* Session對緩存操作:
* flush():使數據庫記錄于緩存中的對象保持一致,為了保持一致可能會放送對應的SQL
* refresh(): 強制放送SELECT語句 使緩存的對象和數據庫中保持一致(一定會發)
* 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();
// 第一次查詢
News news = (News) session.get(News.class, 1);// 并放入緩存
System.out.println(news.toString());
// 第二次查詢 檢查是否緩存 沒有緩存才去查數據庫
News news2 = (News) session.get(News.class, 1);// 不會查詢數據庫
System.out.println(news2.toString());
transaction.commit();
session.close();
sessionFactory.close();
}
- 方法中進行了兩次查詢但只會查詢一次數據
Session對緩存操作:
- flush():使數據庫記錄于緩存中的對象保持一致,為了保持一致可能會放送對應的SQL
- refresh(): 強制發送SELECT語句 使緩存的對象和數據庫中保持一致(一定會發)
- clear():清理緩存
Session緩存flush():數據庫記錄于緩存中的對象保持一致
transaction.commit()方法中先調用Session的flush()方法 在提交事務
flush()的方法可能會放送SQL,但不會提交事務
注意:在未提交事務或顯示調用flush()方法之前,也有可能進行flush()操作
1).執行HQL 或QBC查詢,會先flush()操作,已得到數據表最新記錄
2).若記錄的ID是由底層數據庫自增方式生成的,則在調用save()方法后,會立即放送INSER語句,應為sava方法必須保證對象ID是存在的
/**
*
* Session緩存flush()
*
*
* 1.transaction.commit()方法中向調用Session的flush()方法 在提交事務
* 2.flush()的方法可能會放送SQL,但不會提交事務
* 3.注意:在未提交事務或顯示調用flush()方法之前,也有可能進行flush()操作
* 1).執行HQL 或QBC查詢,會先flush()操作,已得到數據表最新記錄
* 2).若記錄的ID是由底層數據庫自增方式生成的,則在調用save()方法后,會立即放送INSER語句,應為sava方法
* 必須保證對象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(): 使緩存的對象和數據庫中保持一致
/**
* Session緩存refresh()
* 但可能數據不會最新(數據庫的隔離級別)mysql(默認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();
}
會受到數據庫隔離級別的限制
數據庫的隔離級別
串行化(SERIALIZABLE):所有事務都一個接一個地串行執行,這樣可以避免幻讀
可重復讀(REPEATABLE READ):所有被Select獲取的數據都不能被修改,這樣就可以避免一個事務前后讀取數據不一致的情況
讀已提交(READ COMMITED):被讀取的數據可以被其他事務修改。這樣就可能導致不可重復讀
讀未提交(READ UNCOMMITED):這是最低的隔離等級,允許其他事務看到沒有提交的數據。這種等級會導致臟讀
save()方法:對象保存到數據庫
- 1.使一個臨時對象變為持久化對象
- 2.為對象分配id
- 3.在flush緩存使會放送insert語句
- 4.在save之前的id使無效的
- 5.持久化對象id不能修改
/**
* save()方法
* 1.使一個臨時對象變為持久化對象
* 2.為對象分配id
* 3.在flush緩存使會放送insert語句
* 4.在save之前的id使無效的
* 5.持久化對象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()方法:也會執行insert語句 在對象已經有id了,則不會執行insert語句,而拋出異常
/**
* persist()方法
* persist也會執行insert語句 在對象已經有id了,則不會執行insert語句,而拋出異常
* */
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("長沙的測試早", "行啊是從下沙生活", new Date(new Date().getTime()));
session.persist(news);
transaction.commit();
session.close();
sessionFactory.close();
}
get()方法:根據OID回去數據庫數據返回對象
/**
* 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()方法:根據OID回去數據庫數據返回代理對象
- 與get()方法區別:
1.get方法會立即加載對象 load方法若不使用該對象,則不會立即加載對象,返回一個代理對象
2.若數據庫沒有對應記錄 get返回null load 不使用沒有問題 使用拋出異常
3.load 方法可能拋出LazyInitializationException異常:在需要初始化代理對象關閉了session
/**
* load()方法
*
* 與get()方法區別
*
* 1.get方法會立即加載對象 load方法若不使用該對象,則不會立即加載對象,返回一個代理對象
* 2.若數據庫沒有對應記錄 get返回null load 不使用沒有問題 使用拋出異常
* 3.load 方法可能拋出LazyInitializationException異常:在需要初始化代理對象關閉了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()方法:強制使數據庫記錄于對象保持一致
1.若更新一個持久化對象不需要調用update方法,應為在調用commit()方法時,會先執行flush方法
2.更新一個游離對象 需要顯示調用session的update方法,可以把游離對象變為持久化對象
3.無論要更新的游離對象是否和數據庫一致,都會發送SQL語句
4.不讓update順便的發送語句 在.hbm.xml文件的class節點設置 select-before-update="true"他會先查詢,一般不會設置除非和觸發器結合
5.數據庫沒有該對象,會拋出異常
6.關聯一個游離對象時,如果session緩存中有同一個OID的持久化對象會拋出異常,因在session緩存中不能有同一個OID對象
/**
* update()方法
* 1.若更細一個持久化對象不需要調用update方法,應為在調用commit()方法時,會先執行flush方法
* 2.更新一個游離對象 需要顯示調用session的update方法,可以把游離對象變為持久化對象
* 3.無論要更新的游離對象是否和數據庫一致,都會發送SQL語句
* 4.不讓update順便的發送語句 在.hbm.xml文件的class節點設置 select-before-update="true"他會先查詢,一般不會設置除非和觸發器結合
* 5.數據庫沒有該對象,會拋出異常
* 6.關聯一個游離對象時,如果session緩存中有同一個OID的持久化對象會拋出異常,因在session緩存中不能有同一個OID對象
* */
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為空執行insert語句 OID不為空記錄存在執行update語句
- 若OID不為空 數據庫中沒有對應記錄 會拋出異常
/**
* saveOrUpdate()方法 OID為空執行insert語句 OID不為空記錄存在執行update語句
* 1.若OID不為空 數據庫中沒有對應記錄 會拋出異常
* */
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("長沙的測試早", "行啊是從下沙生活", new Date(new Date().getTime()));
session.saveOrUpdate(news);
transaction.commit();
session.close();
sessionFactory.close();
}
delete()方法:刪除數據庫對應數據
- 只要ODI對應記錄存在 刪除 沒有記錄拋出異常 (不分對象狀態 只和OID有關)
- 可以通過設置hibernate配置 <property name="use_identifier_rollback">true</property> 把刪除的對象OID變成null
/**
* delete()方法 只要ODI對應記錄存在 刪除 沒有記錄拋出異常 (不分對象狀態 只和OID有關)
*
* 可以通過設置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("長沙的測試早", "行啊是從下沙生活", new Date(new Date().getTime()));
news.setId(1);
session.delete(news);
transaction.commit();
session.close();
sessionFactory.close();
}
evict()方法:從緩沖中移除指定的持久化對象
/**
* evict()從緩沖中移除指定的持久化對象
* */
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()方法
* 調用數據庫原生的Connection對先
* */
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" 只修改改變的數據表類 性能降低
/**
*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();
}