Hibernate 再接觸 核心開發接口
1.可以重載方法進行配置文件的指定
sessionFactory = new AnnotationConfiguration().configure("hibernate.xml").buildSessionFactory();
這樣讀取到的就是hibernate.xml 但一般不建議修改
getcurrentsession 指的是上下文如果沒有提交 就不會創建新的session
opensession 永遠打開新的session 用於鑒定事務邊界 比如加入日誌操作等
事務:要麽同時完成,要麽就回滾
<property name="current_session_context_class">thread</property>
從當前線程裏找
還有其他幾個參數:
例如 jta ,managed,custorm.class等
thread使用數據庫鏈接作為事務管理
但是管理不了分布式事務
jta(java trasaction api) 往往用在分布式上
需要一個manager管理對部署在兩個數據庫的操作
如果不設上下文他就無法找到
opensession盡量不要跟getcurrentsession同用 不是同一個session
緩存就是內存中的一塊區域 放著我們想要提高讀取效率的對象
對象的三種狀態
Transient persistent detached
Transient 內存有一個對象 但是沒有id 緩存中也沒有 數據庫也沒有
persistent 內存有 緩存中有 數據庫有 也有id session裏有key和value
detached 內存有 緩存沒有 數據庫有
三種狀態區分在於:
有沒有id
id在數據庫中有沒有
在內存中沒有(session緩存)
session 管理一個數據庫的任務單元 管理增刪改查的操作
save 略
delete
只要有id 包括detach態 就可以delete
例如:
@Test public void testDelete() { Teacher t = newTeacher(); t.setName("t1"); t.setTitle("middle"); t.setBirthDate(new Date()); Session session = sessionFactory.getCurrentSession(); session.beginTransaction(); session.save(t); System.out.println(t.getId()); session.getTransaction().commit(); Session session2 = sessionFactory.getCurrentSession(); session2.beginTransaction(); session2.delete(t); session2.getTransaction().commit(); } @Test public void testDelete2() { Teacher t = new Teacher(); t.setId(2); Session session2 = sessionFactory.getCurrentSession(); session2.beginTransaction(); session2.delete(t); session2.getTransaction().commit(); }
Load 讀
@Test public void testLoad() { Session session = sessionFactory.getCurrentSession(); session.beginTransaction(); Teacher t = (Teacher)session.load(Teacher.class, 1); session.getTransaction().commit(); System.out.println(t.getClass()); //System.out.println(t.getName()); }
1 是可以自動打包
get也可以拿數據
@Test public void testGet() { Session session = sessionFactory.getCurrentSession(); session.beginTransaction(); Teacher t = (Teacher)session.get(Teacher.class, 1); session.getTransaction().commit(); System.out.println(t.getClass()); //System.out.println(t.getName()); }
兩者區別:
需要註意的是 get 和load方法有重要區別 load種 是生成一個代理 當真正想使用對象的屬性的時候才會發出sql語句 而get是馬上就發
update
更新detach的一個對象
@Test public void testUpdate1() { Session session = sessionFactory.getCurrentSession(); session.beginTransaction(); Teacher t = (Teacher)session.get(Teacher.class, 1); session.getTransaction().commit(); t.setName("zhanglaoshi"); Session session2 = sessionFactory.getCurrentSession(); session2.beginTransaction(); session2.update(t); session2.getTransaction().commit(); }
更新transient 會報錯 但是更新有id的transient不會報錯 (數據庫有對應記錄)
@Test public void testUpdate4() { Session session = sessionFactory.getCurrentSession(); session.beginTransaction(); Teacher t = (Teacher)session.get(Teacher.class, 1); t.setName("zhangsan2"); session.getTransaction().commit(); }
以上的更新會更新所有字段 為提高效率 所以摸索
如何只改想要的字段
如果是p對象 只要設置字段 就會發生更新
@Test public void testUpdate5() { Session session = sessionFactory.getCurrentSession(); session.beginTransaction(); Student s = (Student)session.get(Student.class, 1); s.setName("zhangsan5"); session.getTransaction().commit(); //發現對象與數據庫中不同 自動update s.setName("z4"); Session session2 = sessionFactory.getCurrentSession(); session2.beginTransaction(); session2.update(s); session2.getTransaction().commit(); }
但是這種更新還是全部的
要想實現只更新想要更新的字段
有三種方法:
1.加上column = false屬性
或者xml加入column = false屬性
2.在xml中加入
<class name="com.bjsxt.hibernate.Student" dynamic-update="true">
這樣在數據庫提交的時候就會只更新自己想改的字段
但是要註意 這個對象一旦在處瑜detach狀態 再提交commit的時候無法作比較 所以就無法更新 所以更新的還是全部字段
@Test public void testUpdate6() { Session session = sessionFactory.getCurrentSession(); session.beginTransaction(); Student s = (Student)session.get(Student.class, 1); s.setName("zhangsan6"); session.getTransaction().commit(); s.setName("z4"); Session session2 = sessionFactory.getCurrentSession(); session2.beginTransaction(); session2.merge(s);//merge可以合並對象 這樣也不用發多余的其他字段的修改 session2.getTransaction().commit(); }
第三種 是hql語句 後面也還會詳細講
@Test public void testUpdate7() { Session session = sessionFactory.getCurrentSession(); session.beginTransaction(); Query q = session.createQuery("update Student s set s.name=‘z5‘ where s.id = 1"); q.executeUpdate(); session.getTransaction().commit(); }
save orupdate
@Test public void testSaveOrUpdate() { Teacher t = new Teacher(); t.setName("t1"); t.setTitle("middle"); t.setBirthDate(new Date()); Session session = sessionFactory.getCurrentSession(); session.beginTransaction(); session.saveOrUpdate(t); session.getTransaction().commit(); t.setName("t2"); Session session2 = sessionFactory.getCurrentSession(); session2.beginTransaction(); session2.saveOrUpdate(t); session2.getTransaction().commit(); }
沒有的話就save 有的話就update
clear
無論是load還是get 都會首先查找緩存(一級緩存),如果沒有 ,才會去數據庫查找,調用clear方法可以強制清除session緩存
@Test public void testClear() { Session session = sessionFactory.getCurrentSession(); session.beginTransaction(); Teacher t = (Teacher)session.load(Teacher.class, 1); System.out.println(t.getName()); session.clear();//如果不加這句話 將只發出一條select sql語句 ,加了之後清除session緩存下面就需要重新發了 Teacher t2 = (Teacher)session.load(Teacher.class, 1); System.out.println(t2.getName()); session.getTransaction().commit(); }
flush方法
強制讓緩存內容與數據庫內容同步
具體在什麽時間flush 是由flushmode設置
@Test public void testFlush() { Session session = sessionFactory.getCurrentSession(); session.beginTransaction(); Teacher t = (Teacher)session.load(Teacher.class, 1); t.setName("tttt"); session.flush(); //強制與數據庫同步,發出update t.setName("ttttt"); session.getTransaction().commit(); //發現不一致 再發出update }
testschemaexport
可以在配置文件中不讓他自動建表
然後自己寫一個類建表
第一個參數這是指是否顯示ddl語句 第二個參數是指是否執行ddl語句
@Test public void testSchemaExport() { new SchemaExport(new AnnotationConfiguration().configure()).create(false, true); }
Hibernate 再接觸 核心開發接口