spring整合hibernate(一)

1.Spring提供的dao支持

DAO模式是標(biāo)準(zhǔn)的java EE設(shè)計(jì)模式,DAO模式的核心思想是所有的數(shù)據(jù)庫訪問,都通過DAO組件完成,DAO組件封裝了數(shù)據(jù)庫的增刪改查等原子操作,業(yè)務(wù)邏輯組件依賴DAO組件提供的原子操作,對于javaEE的應(yīng)用架構(gòu),有非常多的,不管細(xì)節(jié)如何變化,javaEE大致 可以分為如下三層:

<li>表現(xiàn)層;
<li>業(yè)務(wù)邏輯層;
<li>數(shù)據(jù)持久層;

Spring提供了一系列的抽象類,這些抽象類將被作為應(yīng)用中DAO組件可以通過這些抽象類,Spring簡化了DAO的開發(fā)步驟,能夠以一致的訪問方式使用數(shù)據(jù)庫訪問技術(shù),不管底層采用JDBC、JDO還是個(gè)Hibernate,應(yīng)用中都采用一致的編程模型。

Spring提供的多種數(shù)據(jù)庫訪問技術(shù)的DAO支持,包括Hibernate、JDO、TopLink、iBatis、OJB、JPA等,就Hibernate的持久層訪問技術(shù)而言,Spring提供如下3個(gè)工具類來支持DAO組件的實(shí)現(xiàn):HibernateDaoSupport、HibernateTemplate、HibernateCallback


2.管理Hibernate的SessionFactory:

面介紹的Hibernate的時(shí)候知道:通過Hibernate進(jìn)行持久層訪問的時(shí)候,Hibernate的SessionFactory是非常重要的對象,它是單個(gè)數(shù)據(jù)庫映射關(guān)系編譯后的內(nèi)存鏡像,大部分情況下,一個(gè)java EE應(yīng)用對應(yīng)一個(gè)數(shù)據(jù)庫,即對應(yīng)一個(gè)SessionFactory對象。

配置SessionFactory的示范代碼:

<!-- 定義數(shù)據(jù)源Bean,使用C3P0數(shù)據(jù)源實(shí)現(xiàn) -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
        destroy-method="close">
        <!-- 指定連接數(shù)據(jù)庫的驅(qū)動(dòng) -->
        <property name="driverClass" value="com.mysql.jdbc.Driver"/>
        <!-- 指定連接數(shù)據(jù)庫的URL -->
        <property name="jdbcUrl" value="jdbc:mysql://localhost/javaee"/>
        <!-- 指定連接數(shù)據(jù)庫的用戶名 -->
        <property name="user" value="root"/>
        <!-- 指定連接數(shù)據(jù)庫的密碼 -->
        <property name="password" value="32147"/>
        <!-- 指定連接數(shù)據(jù)庫連接池的最大連接數(shù) -->
        <property name="maxPoolSize" value="40"/>
        <!-- 指定連接數(shù)據(jù)庫連接池的最小連接數(shù) -->
        <property name="minPoolSize" value="1"/>
        <!-- 指定連接數(shù)據(jù)庫連接池的初始化連接數(shù) -->
        <property name="initialPoolSize" value="1"/>
        <!-- 指定連接數(shù)據(jù)庫連接池的連接的最大空閑時(shí)間 -->
        <property name="maxIdleTime" value="20"/>
    </bean>
    <!-- 定義Hibernate的SessionFactory -->
    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <!-- 依賴注入數(shù)據(jù)源,注入正是上面定義的dataSource -->
        <property name="dataSource" ref="dataSource"/>
        <!-- mappingResouces屬性用來列出全部映射文件 -->
        <property name="mappingResources">
            <list>
                <!-- 以下用來列出Hibernate映射文件 -->
                <value>Person.hbm.xml</value>
            </list>
        </property>
        <!-- 定義Hibernate的SessionFactory的屬性 -->
        <property name="hibernateProperties">
            <props>
                <!-- 指定數(shù)據(jù)庫方言 -->
                <prop key="hibernate.dialect">
                    org.hibernate.dialect.MySQLInnoDBDialect</prop>
                <!-- 是否根據(jù)需要每次自動(dòng)創(chuàng)建數(shù)據(jù)庫 -->
                <prop key="hibernate.hbm2ddl.auto">update</prop>
                <!-- 顯示Hibernate持久化操作所生成的SQL -->
                <prop key="hibernate.show_sql">true</prop>
                <!-- 將SQL腳本進(jìn)行格式化后再輸出 -->
                <prop key="hibernate.format_sql">true</prop>
            </props>
        </property>
    </bean>

3.使用HibernateTemplate

HibernateTemplate提供持久層訪問模版化,它只需要提供一個(gè)SessionFactory的引用,SessionFactory可以通過構(gòu)造方法參數(shù)傳入,也可以通過設(shè)值方式傳入。

示例:

public class PersonDaoImpl implements PersonDao
{
    //定義一個(gè)HibernateTemplate對象,用于執(zhí)行持久化操作
    private HibernateTemplate ht = null;
    //Hibernate持久化操作所需的SessionFactory
    private SessionFactory sessionFactory;
    //依賴注入SessionFactory的setter方法
    public void setSessionFactory(SessionFactory sessionFactory)
    {
        this.sessionFactory = sessionFactory;
    }
    //初始化HibernateTemplate的方法
    private HibernateTemplate getHibernateTemplate()
    {
        if (ht == null)
        {
            ht = new HibernateTemplate(sessionFactory);
        }
        return ht;
    }
    /**
     * 加載Person實(shí)例
     * @param id 需要加載的Person實(shí)例的標(biāo)識屬性值
     * @return 指定id對應(yīng)的Person實(shí)例
     */ 
    public Person get(Integer id)
    {
        return (Person)getHibernateTemplate()
            .get(Person.class, id); 
    }

    /**
     * 保存Person實(shí)例
     * @param person 需要保存的Person實(shí)例
     * @return 剛剛保存的Person實(shí)例的標(biāo)識屬性值
     */   
    public Integer save(Person person)
    {
        return (Integer)getHibernateTemplate()
            .save(person);
    }

    /**
     * 修改Person實(shí)例
     * @param person 需要修改的Person實(shí)例
     */
    public void update(Person person)
    {
        getHibernateTemplate().update(person);
    }

    /**
     * 刪除Person實(shí)例
     * @param id 需要?jiǎng)h除的Person實(shí)例的標(biāo)識屬性值
     */
    public void delete(Integer id)
    {
        getHibernateTemplate().delete(get(id));
    }

    /**
     * 刪除Person實(shí)例
     * @param person 需要?jiǎng)h除的Person實(shí)例
     */
    public void delete(Person person)
    {
        getHibernateTemplate().delete(person);
    }

    /**
     * 根據(jù)用戶名查找Person
     * @param name 查詢的人名
     * @return 指定用戶名對應(yīng)的全部Person
     */
    public List<Person> findByName(String name)
    {
        return (List<Person>)getHibernateTemplate()
            .find("from Person p where p.name like ?" , name);
    }

    /**
     * 查詢?nèi)縋erson實(shí)例
     * @return 全部Person實(shí)例
     */
    public List findAllPerson()
    {
        return (List<Person>)getHibernateTemplate()
            .find("from Person");
    }

    /**
     * 查詢數(shù)據(jù)表中Person實(shí)例的總數(shù)
     * @return 數(shù)據(jù)表中Person實(shí)例的總數(shù)
     */
    public long getPersonNumber()
    {
        return (Long)getHibernateTemplate().find
            ("select count(*) from Person as p")
            .get(0);
    }
}

4.使用HibernateCallback

HibernateTemplate還提供一種更加靈活的方式來操作數(shù)據(jù)庫,,通過這種方式可以完全使用Hibernate的操作方式,HibernateTemplate的靈活方式是通過如下兩個(gè)方法來完成的。

Object execute(HibernateCallback action);
List executeFind(HibernateCallback action);

這兩個(gè)方法都需要一個(gè)HibernateCallback實(shí)例,HibernateCallback是一個(gè)接口,該接口包含一個(gè)方法doInHibernate(org.hibernate Session session),該方法是有一個(gè)Session參數(shù),當(dāng)我們在開發(fā)中提供HibernateCallback實(shí)現(xiàn)類時(shí),必須實(shí)現(xiàn)接口里的doInHibernate方法,該方法體內(nèi)即可獲得 Hibernate Session的引用。一旦獲取到Session的引用我們就可以完全以Hibernate的方式進(jìn)行數(shù)據(jù)庫的訪問。

示例:

public class YeekuHibernateDaoSupport extends HibernateDaoSupport
{
    /**
     * 使用hql語句進(jìn)行分頁查詢
     * @param hql 需要查詢的hql語句
     * @param offset 第一條記錄索引
     * @param pageSize 每頁需要顯示的記錄數(shù)
     * @return 當(dāng)前頁的所有記錄
     */
    public List findByPage(final String hql, 
        final int offset, final int pageSize)
    {
        //通過一個(gè)HibernateCallback對象來執(zhí)行查詢
        List list = getHibernateTemplate()
            .executeFind(new HibernateCallback()
        {
            //實(shí)現(xiàn)HibernateCallback接口必須實(shí)現(xiàn)的方法
            public Object doInHibernate(Session session)
                throws HibernateException, SQLException
            {
                //執(zhí)行Hibernate分頁查詢
                List result = session.createQuery(hql)
                    .setFirstResult(offset)
                    .setMaxResults(pageSize)
                    .list();
                return result;
            }
        });
        return list;
    }

    /**
     * 使用hql語句進(jìn)行分頁查詢
     * @param hql 需要查詢的hql語句
     * @param value 如果hql有一個(gè)參數(shù)需要傳入,value就是傳入hql語句的參數(shù)
     * @param offset 第一條記錄索引
     * @param pageSize 每頁需要顯示的記錄數(shù)
     * @return 當(dāng)前頁的所有記錄
     */
    public List findByPage(final String hql , final Object value ,
        final int offset, final int pageSize)
    {
        //通過一個(gè)HibernateCallback對象來執(zhí)行查詢
        List list = getHibernateTemplate()
            .executeFind(new HibernateCallback()
        {
            //實(shí)現(xiàn)HibernateCallback接口必須實(shí)現(xiàn)的方法
            public Object doInHibernate(Session session)
                throws HibernateException, SQLException
            {
                //執(zhí)行Hibernate分頁查詢
                List result = session.createQuery(hql)
                    //為hql語句傳入?yún)?shù)
                    .setParameter(0, value) 
                    .setFirstResult(offset)
                    .setMaxResults(pageSize)
                    .list();
                return result;
            }
        });
        return list;
    }

    /**
     * 使用hql語句進(jìn)行分頁查詢
     * @param hql 需要查詢的hql語句
     * @param values 如果hql有多個(gè)個(gè)參數(shù)需要傳入,values就是傳入hql的參數(shù)數(shù)組
     * @param offset 第一條記錄索引
     * @param pageSize 每頁需要顯示的記錄數(shù)
     * @return 當(dāng)前頁的所有記錄
     */
    public List findByPage(final String hql, final Object[] values,
        final int offset, final int pageSize)
    {
        //通過一個(gè)HibernateCallback對象來執(zhí)行查詢
        List list = getHibernateTemplate()
            .executeFind(new HibernateCallback()
        {
            //實(shí)現(xiàn)HibernateCallback接口必須實(shí)現(xiàn)的方法
            public Object doInHibernate(Session session)
                throws HibernateException, SQLException
            {
                //執(zhí)行Hibernate分頁查詢
                Query query = session.createQuery(hql);
                //為hql語句傳入?yún)?shù)
                for (int i = 0 ; i < values.length ; i++)
                {
                    query.setParameter( i, values[i]);
                }
                List result = query.setFirstResult(offset)
                    .setMaxResults(pageSize)
                    .list();
                return result;
            }
        });
        return list;
    }
}

Spring提供了XxxTemplate和XxxCallback互為補(bǔ)充,XxxTemplate對操作進(jìn)行封裝,XxxCallback解決了封裝后靈活性不足的缺陷。


5.實(shí)現(xiàn)DAO組件

為了實(shí)現(xiàn)DAO組件,Spring提供了大量的XxxDaoSupport類,這些dao支持類已經(jīng)完成了大量基礎(chǔ)性的工作。

Spring為Hibernate的DAO提供工具類:HibernateDaoSupport,該類主要提供如下幾個(gè)方法來簡化DAO的實(shí)現(xiàn):

public final HibernateTemplate getHibernateTemplate ();
public final void setSessionFactory(SessionFactory sessionFactory);

setSessionFactory方法可用于接收Spring的依賴注入,允許使用依賴注入Spring 管理的SessionFactory實(shí)例。

public class PersonDaoHibernate
    extends HibernateDaoSupport implements PersonDao
{
    /**
     * 加載Person實(shí)例
     * @param id 需要加載的Person實(shí)例的標(biāo)識屬性值
     * @return 指定id對應(yīng)的Person實(shí)例
     */ 
    public Person get(Integer id)
    {
        return (Person)getHibernateTemplate()
            .get(Person.class, id); 
    }

    /**
     * 保存Person實(shí)例
     * @param person 需要保存的Person實(shí)例
     * @return 剛剛保存的Person實(shí)例的標(biāo)識屬性值
     */   
    public Integer save(Person person)
    {
        return (Integer)getHibernateTemplate()
            .save(person);
    }

    /**
     * 修改Person實(shí)例
     * @param person 需要修改的Person實(shí)例
     */
    public void update(Person person)
    {
        getHibernateTemplate().update(person);
    }

    /**
     * 刪除Person實(shí)例
     * @param id 需要?jiǎng)h除的Person實(shí)例的標(biāo)識屬性值
     */
    public void delete(Integer id)
    {
        getHibernateTemplate().delete(get(id));
    }

    /**
     * 刪除Person實(shí)例
     * @param person 需要?jiǎng)h除的Person實(shí)例
     */
    public void delete(Person person)
    {
        getHibernateTemplate().delete(person);
    }

    /**
     * 根據(jù)用戶名查找Person
     * @param name 查詢的人名
     * @return 指定用戶名對應(yīng)的全部Person
     */
    public List<Person> findByName(String name)
    {
        return (List<Person>)getHibernateTemplate()
            .find("from Person p where p.name like ?" , name);
    }

    /**
     * 查詢?nèi)縋erson實(shí)例
     * @return 全部Person實(shí)例
     */
    public List findAllPerson()
    {
        return (List<Person>)getHibernateTemplate()
            .find("from Person");
    }
}

實(shí)際上,DAO的實(shí)現(xiàn)依然借助于HibernateTemplate的模板訪問方式,只是HibernateDaoSupport提供了兩個(gè)工具方法。

至此Java EE應(yīng)用所需的各種組件都已經(jīng)出現(xiàn)了。

從用戶的角度上看,用戶發(fā)出HTTP請求,當(dāng)MVC框架的控制器組件攔截到用戶的請求,將調(diào)用系統(tǒng)的業(yè)務(wù)邏輯組件,業(yè)務(wù)邏輯組件則調(diào)用 系統(tǒng)的DAO組件,,而DAO組件則依賴于SessionFactory和DataSOurce等底層的實(shí)現(xiàn)數(shù)據(jù)庫訪問。

從系統(tǒng)的實(shí)現(xiàn)角度上看,IoC容器先創(chuàng)建SessionFactory和DataSource等底層組件,然后將這些組件注入DAO組件,提供一個(gè)完整的Dao組件,并將DAO組件注入給業(yè)務(wù)邏輯組件,從而提供一個(gè)完整的業(yè)務(wù)邏輯組件,而業(yè)務(wù)邏輯組件又被注入給控制器組件,控制器組件負(fù)責(zé)攔截用戶請求,并將處理結(jié)果呈現(xiàn)給用戶。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 34,767評論 18 399
  • 這部分主要是開源Java EE框架方面的內(nèi)容,包括Hibernate、MyBatis、Spring、Spring ...
    雜貨鋪老板閱讀 1,571評論 0 2
  • 一. Java基礎(chǔ)部分.................................................
    wy_sure閱讀 4,017評論 0 11
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,662評論 19 139
  • 問題描述: 1、手機(jī)和模擬器可以正常Run; 2、手機(jī)不能Debug,模擬器可以正常Debug; 3、其他程序可以...
    魏祥明閱讀 1,252評論 0 1

友情鏈接更多精彩內(nèi)容