Hibernate學習3(Session概述與方法)

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();
    }
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容