1. 程式人生 > >【Hibernate】getHibernateTemplate.find()和session.createQuery()方法總結

【Hibernate】getHibernateTemplate.find()和session.createQuery()方法總結

Spring中常用的hql查詢方法(getHibernateTemplate().find())

一、find(String queryString);

 示例:this.getHibernateTemplate().find("from bean.User"); 

 返回所有User物件 

二、find(String queryString , Object value);

 示例:this.getHibernateTemplate().find("from bean.User u where u.name=?", "test"); 
 或模糊查詢:this.getHibernateTemplate().find("from bean.User u where u.name like ?", "%test%"); 

 返回name屬性值為test的物件(模糊查詢,返回name屬性值包含test的物件) 

三、find(String queryString, Object[] values);

 示例:String hql= "from bean.User u where u.name=? and u.password=?" 
           this.getHibernateTemplate().find(hql, new String[]{"test", "123"}); 

 返回使用者名稱為test並且密碼為123的所有User物件 

        u.setName("bb");    
        list=this.getHibernateTemplate().findByExample(u,start,max);  

 返回:使用者名稱為bb密碼為123的物件 

---------------------------------

四、findByExample(Object exampleEntity)

 示例: 

        User u=new User();    
        u.setPassword("123");//必須 符合的條件但是這兩個條件時並列的(象當於sql中的and)    
        u.setName("bb");    
        list=this.getHibernateTemplate().findByExample(u,start,max);  

 返回:使用者名稱為bb密碼為123的物件 

五、findByExample(Object exampleEntity, int firstResult, int maxResults)

 示例: 

       User u=new User();    
       u.setPassword("123");//必須 符合的條件但是這兩個條件時並列的(象當於sql中的and)    
       u.setName("bb");    
       list=this.getHibernateTemplate().findByExample(u,start,max);    

 返回:滿足使用者名稱為bb密碼為123,自start起共max個User物件。(物件從0開始計數) 

六、findByNamedParam(String queryString , String paramName , Object value)

使用以下語句查詢:

    String queryString = "select count(*) from bean.User u where u.name=:myName"; 
    String paramName= "myName"; 
    String value= "xiyue"; 
    this.getHibernateTemplate().findByNamedParam(queryString, paramName, value); 
    System.out.println(list.get(0)); 

返回name為xiyue的User物件的條數 

七、findByNamedParam(String queryString , String[] paramName , Object[] value)

 示例: 

    String queryString = "select count(*) from bean.User u where u.name=:myName and u.password=:myPassword"; 
    String[] paramName= new String[]{"myName", "myPassword"}; 
    String[] value= new String[]{"xiyue", "123"}; 
    this.getHibernateTemplate().findByNamedParam(queryString, paramName, value); 

    返回使用者名稱為xiyue密碼為123的User物件 

八、findByNamedQuery(String queryName)

 示例: 

   1、首先需要在User.hbm.xml中定義命名查詢 

        <hibernate-mapping> 
             <class>......</class> 
             <query name="queryAllUser"><!--此查詢被呼叫的名字--> 
                  <![CDATA[ 
                       from bean.User 
                   ]]> 
             </query> 
        </hibernate-mapping> 

    2、如下使用查詢: 

        this.getHibernateTemplate().findByNamedQuery("queryAllUser"); 

九、findByNamedQuery(String queryName, Object value)

 示例: 

   1、首先需要在User.hbm.xml中定義命名查詢 

        <hibernate-mapping> 
             <class>......</class> 
             <query name="queryByName"><!--此查詢被呼叫的名字--> 
                  <![CDATA[ 
                       from bean.User u where u.name = ? 
                   ]]> 
             </query> 
        </hibernate-mapping> 

    2、如下使用查詢: 

        this.getHibernateTemplate().findByNamedQuery("queryByName", "test"); 

十、findByNamedQuery(String queryName, Object[] value)

 示例: 

   1、首先需要在User.hbm.xml中定義命名查詢 

        <hibernate-mapping> 
             <class>......</class> 
             <query name="queryByNameAndPassword"><!--此查詢被呼叫的名字--> 
                  <![CDATA[ 
                       from bean.User u where u.name =? and u.password =? 
                   ]]> 
             </query> 
        </hibernate-mapping> 

    2、如下使用查詢: 

        String[] values= new String[]{"test", "123"}; 
        this.getHibernateTemplate().findByNamedQuery("queryByNameAndPassword" , values); 

十一、findByNamedQueryAndNamedParam(String queryName, String paramName, Object value)

示例:

   1、首先需要在User.hbm.xml中定義命名查詢 

        <hibernate-mapping> 
             <class>......</class> 
             <query name="queryByName"><!--此查詢被呼叫的名字--> 
                  <![CDATA[ 
                       from bean.User u where u.name =:myName 
                   ]]> 
             </query> 
        </hibernate-mapping> 

    2、如下使用查詢: 

        this.getHibernateTemplate().findByNamedQuery("queryByName" , "myName", "test"); 

十二、findByNamedQueryAndNamedParam(String queryName, String[] paramName, Object[] value)

示例:

   1、首先需要在User.hbm.xml中定義命名查詢 

        <hibernate-mapping> 
             <class>......</class> 
             <query name="queryByNameAndPassword"><!--此查詢被呼叫的名字--> 
                  <![CDATA[ 
                       from bean.User u where u.name =:myName and u.password=:myPassword 
                   ]]> 
             </query> 
        </hibernate-mapping> 

    2、如下使用查詢: 

        String[] names= new String[]{"myName", "myPassword"}; 
        String[] values= new String[]{"test", "123"}; 
        this.getHibernateTemplate().findByNamedQuery("queryByNameAndPassword" , names, values); 

十三、findByValueBean(String queryString , Object value);

示例:

 1、定義一個ValueBean,屬性名必須和HSQL語句中的:後面的變數名同名,此處必須至少有兩個屬性,分別為myName和myPassword,使用setter方法設定屬性值後 

     ValueBean valueBean= new ValueBean(); 
     valueBean.setMyName("test"); 
     valueBean.setMyPasswrod("123"); 

 2、 

     String queryString= "from bean.User u where u.name=:myName and u.password=:myPassword"; 
     this.getHibernateTemplate().findByValueBean(queryString , valueBean);  

十四、findByNamedQueryAndValueBean(String queryName , Object value);

示例:

  1、首先需要在User.hbm.xml中定義命名查詢 

        <hibernate-mapping> 
             <class>......</class> 
             <query name="queryByNameAndPassword"><!--此查詢被呼叫的名字--> 
                  <![CDATA[ 
                       from bean.User u where u.name =:myName and u.password=:myPassword 
                   ]]> 
             </query> 
        </hibernate-mapping> 

 2、定義一個ValueBean,屬性名必須和User.hbm.xml命名查詢語句中的:後面的變數名同名,此處必須至少有兩個屬性,分別為myName和myPassword,使用setter方法設定屬性值後 

     ValueBean valueBean= new ValueBean(); 

     valueBean.setMyName("test"); 

     valueBean.setMyPasswrod("123"); 

 3、 

     String queryString= "from bean.User u where u.name=:myName and u.password=:myPassword"; 

     this.getHibernateTemplate().findByNamedQueryAndValueBean("queryByNameAndPassword", valueBean);

session的createQuery()方法總結

使用SQLQuery對原生SQL查詢執行的控制是通過SQLQuery介面進行的,通過執行Session.createSQLQuery()獲取這個介面。最簡單的情況下,我們可以採用以下形式:

List cats = sess.createSQLQuery( " select * from cats " ).addEntity(Cat. class ).list();

這個查詢指定了:SQL查詢字串 和查詢返回的實體

這裡,結果集欄位名被假設為與對映檔案中指明的欄位名相同。對於連線了多個表的查詢,這就可能造成問題,因為可能在多個表中出現同樣名字的欄位。下面的方法就可以避免欄位名重複的問題:

List cats = sess.createSQLQuery( " select {cat.*} from cats cat " ).addEntity( " cat " , Cat. class ).list();

這個查詢指定了:

SQL查詢語句,它帶一個佔位符,可以讓Hibernate使用欄位的別名.
查詢返回的實體,和它的SQL表的別名.

addEntity()方法將SQL表的別名和實體類聯絡起來,並且確定查詢結果集的形態。

addJoin()方法可以被用於載入其他的實體和集合的關聯.

List cats = sess.createSQLQuery(" select {cat.*}, {kitten.*} from cats cat, cats kitten where kitten.mother = cat.id " )
.addEntity( " cat " , Cat. class ).addJoin( " kitten " , " cat.kittens " )
.list();

原生的SQL查詢可能返回一個簡單的標量值或者一個標量和實體的結合體。

Double max = (Double) sess.createSQLQuery( " select max(cat.weight) as maxWeight from cats cat " )
.addScalar( " maxWeight " , Hibernate.DOUBLE).uniqueResult();

除此之外,你還可以在你的hbm檔案中描述結果集對映資訊,在查詢中使用。

List cats = sess.createSQLQuery(" select {cat.*}, {kitten.*} from cats cat, cats kitten where kitten.mother = cat.id " )
.setResultSetMapping( " catAndKitten " ).list();

命名SQL查詢可以在對映文件中定義查詢的名字,然後就可以象呼叫一個命名的HQL查詢一樣直接呼叫命名SQL查詢.在這種情況下,我們不 需要呼叫addEntity()方法.

< sql - query name = " persons " >
< return alias = " person " class = " eg.Person " />
Select person.NAME AS {person.name},person.AGE AS {person.age},person.SEX AS {person.sex} FROM PERSON person Where person.NAME LIKE :namePattern
</ sql - query >List people = sess.getNamedQuery( " persons " ).setString( " namePattern " , namePattern).setMaxResults( 50 ).list();

原來的查詢語句:

String sql = "select a.* from tb_doc_catalog a where a.cat_code like '"+catCode+"%'";
Session session = this.getSession();
try {
    List catNameList = session.createSQLQuery(sql).list();
    return catNameList ;
} finally {
    releaseSession(session); //釋放session
}

分析:原來是查詢出來的欄位並不能自動轉換為bean物件。

解決思路一(採用hql查詢):

String sql = "select a from DocCatalogInfo a where a.catCode like '"+catCode+"%'";
List catNameList =getHibernateTemplate().find(sql);
return catNameList ;

測試一下發現沒問題,看來還是因為用原生sql查詢的原因,網上搜一下:createsqlQuery返回物件,看到一篇文章才覺悟到:

解決思路二(採用原生sql查詢):

String sql = "select a.* from tb_doc_catalog a where a.cat_code like '"+catCode+"%'";
Session session = this.getSession();
try {
    List catNameList = session.createSQLQuery(sql).addEntity(DocCatalogInfo.class).list();
    return catNameList ;
} finally {
    releaseSession(session); //釋放session
}

下面我們來總結一下hibernate 中createQuery與createSQLQuery兩者區別:

1、前者用的hql語句進行查詢,後者可以用sql語句查詢。
2、前者以hibernate生成的Bean為物件裝入list返回,後者則是以物件陣列進行儲存。

所以使用createSQLQuery有時候也想以hibernate生成的Bean為物件裝入list返回,就不是很方便。
突然發現createSQLQuery有這樣一個方法可以直接轉換物件:

Query query = session.createSQLQuery(sql).addEntity(XXXXXXX.class);

XXXXXXX 代表以hibernate生成的Bean的物件,也就是資料表映射出的Bean。

以後多注意,還是時不時的要看看hibernate各個物件方法的使用。

還有另外一個相關的小細節應注意:
比如有這樣一個po

PO: User.class
properties: userId,userName
DDL: create table tuser (userid varchar(10),username varchar(20));

當執行:session.createQuery(“from User u”).list()時生成的SQL:select userid,username from tuser;
當執行:session.createQuery(“from User u”).iterator()時生成的SQL:select userid from tuser;

可以看出list()一次將資料從資料庫中讀出直接填充到List中,iterator()將資料的主鍵從資料庫中讀出,當迴圈這個Iterator時才新增執行:

select userid,username from user where userid=?;把資料讀出。

在不同的應用範圍使用不同的方法,具體在hibernate應用中應當注意。

用法一(返回數值):

ISQLQuery query = session.CreateSQLQuery("SELECT COUNT(Id) AS C FROM Cake").AddScalar("C", NHibernateUtil.Int32);
int c = Convert.ToInt32(query.UniqueResult());
或int c = query.UniqueResult<int>;//使用此方法發現sql執行了兩次,故不推薦使用。

用法二(返回物件實體):

ISQLQuery query = session.CreateSQLQuery("select * from cake c").AddEntity("CAKE.DataTransfer.Entities.Cake");
或ISQLQuery query = session.CreateSQLQuery("select * from cake c").AddEntity("c", "CAKE.DataTransfer.Entities.Cake");
或ISQLQuery query = session.CreateSQLQuery("select * from cake c").AddEntity(typeof(Cake));
或ISQLQuery query = session.CreateSQLQuery("select * from cake c").AddEntity("c", typeof(Cake));
或ISQLQuery query = session.CreateSQLQuery("select * from cake c").AddEntity("c", typeof(Cake), LockMode.Write);

IList<Cake> c = query.List<Cake>();

用法三(連表查詢):

ISQLQuery query = session.CreateSQLQuery("select cs.* from cake c join CakeSize cs on cs.CakeId=c.Id").AddEntity("cs", typeof(CakeSize));
IList<CakeSize> cs = query.List<CakeSize>();

以上是一種常見的用法,通過該例子,相信大家心裡也已經有個數了,也應該知道怎麼操作這個sql了:

但是過程中難免會遇到些問題,比如:

例項二(問題說明):

我需要執行例如這條sql語句:

select CreateTime,Address,Password, (case when EmailType = 0 then 'Gmail' when EmailType = 1 then 'Yahoo' when EmailType = 2 then 'Hotmail' else 'Other' end) as EmailType from MailInfo
  1. 如果使用session.CreateQuery方法執行的話,你可能會遇到這樣的錯誤:

錯誤:undefined alias or unknown mapping

ISession session = DAORepository.Instrance.DbSession;
string queryString = "select CreateTime,Address,Password, (case when EmailType = 0 then 'Gmail' when EmailType = 1 then 'Yahoo' when EmailType = 2 then 'Hotmail' else 'Other' end) as EmailType from MailInfo where status=0 Order by CreateTime desc";
IQuery query = session.CreateQuery(queryString;
IList lst = query.List();
  1. 使用CreateSQLQuery方法執行:

錯誤:Return types of SQL query were not specified…

ISession session = DAORepository.Instrance.DbSession;
string queryString = "select CreateTime,Address,Password, (case when EmailType = 0 then 'Gmail' when EmailType = 1 then 'Yahoo' when EmailType = 2 then 'Hotmail' else 'Other' end) as EmailType from MailInfo where status=0 Order by CreateTime desc";
ISQLQuery query = session.CreateSQLQuery(queryString);
IList lst = query.List();
  1. 使用CreateSQLQuery方法並指定返回欄位值的型別,即使用AddScalar方法指定欄位值型別:

錯誤:could not execute query…

ISession session = DAORepository.Instrance.DbSession;
string queryString = "select CreateTime,Address,Password, (case when EmailType = 0 then 'Gmail' when EmailType = 1 then 'Yahoo' when EmailType = 2 then 'Hotmail' else 'Other' end) as EmailType from MailInfo where status=0 Order by CreateTime desc";
ISQLQuery query = session.CreateSQLQuery(queryString).AddScalar("CreateTime",NHibernateUtil.String)
.AddScalar("Address",NHibernateUtil.String)
.AddScalar("Password",NHibernateUtil.String)
.AddScalar("EmailType",NHibernateUtil.Int32);
IList lst = query.List();
ISession session = DAORepository.Instrance.DbSession;
string queryString = "select CreateTime,Address,Password, (case when EmailType = 0 then 'Gmail' when EmailType = 1 then 'Yahoo' when EmailType = 2 then 'Hotmail' else 'Other' end) as EmailType from MailInfo where status=0 Order by CreateTime desc";
ISQLQuery query = session.CreateSQLQuery(queryString)
.AddScalar("CreateTime",NHibernateUtil.String)
.AddScalar("Address",NHibernateUtil.String)
.AddScalar("Password",NHibernateUtil.String)
.AddScalar("EmailType",NHibernateUtil.Int32);
IList lst = query.List();

注意:EmailType欄位對應資料庫的型別是int,這裡我就誤解為也應該對映為NHibernateUtil.Int32;

  1. 解決問題:

把AddScalar方法的引數裡一個屬性改了一下:

ISession session = DAORepository.Instrance.DbSession;
string queryString = "select CreateTime,Address,Password, (case when EmailType = 0 then 'Gmail' when EmailType = 1 then 'Yahoo' when EmailType = 2 then 'Hotmail' else 'Other' end) as EmailType from MailInfo where status=0 Order by CreateTime desc";
ISQLQuery query = session.CreateSQLQuery(queryString).AddScalar("CreateTime",NHibernateUtil.String)
.AddScalar("Address",NHibernateUtil.String)
.AddScalar("Password",NHibernateUtil.String)
.AddScalar("EmailType",NHibernateUtil.String);
IList lst = query.List();
ISession session = DAORepository.Instrance.DbSession;
string queryString = "select CreateTime,Address,Password, (case when EmailType = 0 then 'Gmail' when EmailType = 1 then 'Yahoo' when EmailType = 2 then 'Hotmail' else 'Other' end) as EmailType from MailInfo where status=0 Order by CreateTime desc";
ISQLQuery query = session.CreateSQLQuery(queryString)
.AddScalar("CreateTime",NHibernateUtil.String)
.AddScalar("Address",NHibernateUtil.String)
.AddScalar("Password",NHibernateUtil.String)
.AddScalar("EmailType",NHibernateUtil.String);
IList lst = query.List();