1. 各位大俠們,hibernate怎麼完成動態生成sql語句的啊
Hibernate3支持DetachedCriteria,這是一個非常有意義的特性!我們知道,在常規的Web編程中,有大量的動態條件查詢,即用戶在網頁上面自由選擇某些條件,程序根據用戶的選擇條件,動態生成SQL語句,進行查詢。針對這種需求,對於分層應用程序來說,Web層需要傳遞一個查詢的條件列表給業務層對象,業務層對象獲得這個條件列表之後,然後依次取出條件,構造查詢語句。這里的一個難點是條件列表用什麼來構造?傳統上使用Map,但是這種方式缺陷很大,Map可以傳遞的信息非常有限,只能傳遞name和value,無法傳遞究竟要做怎樣的條件運算,究竟是大於,小於,like,還是其它的什麼,業務層對象必須確切掌握每條entry的隱含條件。因此一旦隱含條件改變,業務層對象的查詢構造演算法必須相應修改,但是這種查詢條件的改變是隱式約定的,而不是程序代碼約束的,因此非常容易出錯。DetachedCriteria可以解決這個問題,即在web層,程序員使用DetachedCriteria來構造查詢條件,然後將這個DetachedCriteria作為方法調用參數傳遞給業務層對象。而業務層對象獲得DetachedCriteria之後,可以在session范圍內直接構造Criteria,進行查詢。就此,查詢語句的構造完全被搬離到web層實現,而業務層則只負責完成持久化和查詢的封裝即可,與查詢條件構造完全解耦,非常完美!這恐怕也是以前很多企圖在web層代碼中構造HQL語句的人想實現的夢想吧!示例代碼片段如下:web層程序構造查詢條件:java代碼:DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Department.class);
detachedCriteria.add(Restrictions.eq("name", "department")).createAlias("employees", "e").add(Restrictions.gt(("e.age"), new Integer(20)));Department和Employee是一對多關聯,查詢條件為:名稱是「department」開發部門;
部門裡面的雇員年齡大於20歲;業務層對象使用該條件執行查詢:java代碼:detachedCriteria.getExecutableCriteria(session).list();最大的意義在於,業務層代碼是固定不變的,所有查詢條件的構造都在web層完成,業務層只負責在session內執行之。這樣代碼就可放之四海而皆準,都無須修改了。然而Spring和Hibernate3的DetachedCriteria有不兼容的問題,因此在Spring環境下面使用Hibernate3需要注意:Spring的HibernateTemplate提供了Hibernate的完美封裝,即通過匿名類實現回調,來保證Session的自動資源管理和事務的管理。其中核心方法是:java代碼:HibernateTemplate.execute(new HibernateCallback() {
public Object doInHibernate(Session session) throws HibernateException {
....
}
}回調方法提供了session作為參數,有了session,就可以自由的使用Hibernate API編程了。使用了spring的之後,代碼修改如下:web層代碼:java代碼:DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Department.class);
detachedCriteria.createAlias("employees", "e").add(Restrictions.eq("name", "department")).add(Restrictions.gt(("e.age"), new Integer(20)));
departmentManager.findByCriteria(detachedCriteria);構造detachedCriteria,作為參數傳遞給departmentManager業務層代碼使用spring,DepartmentManager的findByCriteria如下:java代碼:public List findByCriteria(final DetachedCriteria detachedCriteria) {
return (List) getHibernateTemplate().execute(new HibernateCallback() {
public Object doInHibernate(Session session) throws HibernateException {
Criteria criteria = detachedCriteria.getExecutableCriteria(session);
return criteria.list();
}
});
}實際上也就是:java代碼:Criteria criteria = detachedCriteria.getExecutableCriteria(session);
return criteria.list(); 而已但是該程序代碼執行,會拋出強制類型轉換異常!我跟蹤了一下spring和Hibernate源代碼,原因如下:spring的HibernateTemplate的execute方法提供的回調介面具有Session作為參數,但是實際上,默認情況下,HibernateTemplate傳遞給回調介面的session並不是org.hibernate.impl.SessionImpl類,而是SessionImpl類的一個Proxy類。之所以替換成為一個Proxy類,HibernateTemplate的注釋說明,Proxy提供了一些額外的功能,包括自動設置Cachable,Transaction的超時時間,Session資源的更積極的關閉等等。java代碼:private boolean exposeNativeSession = false;
... execute方法內部:Session sessionToExpose = (exposeNativeSession ? session : createSessionProxy(session));但是遺憾的是,Hibernate的DetachedCriteria的setExecutableCriteria方法卻要求將session參數強制轉為SessionImpl,但是spring傳過來的卻是一個Proxy類,因此就報錯了。java代碼:public Criteria getExecutableCriteria(Session session) {
impl.setSession( (SessionImpl) session ); // 要求SessionImpl,Spring傳遞的是Proxy
return impl;
}解決方法,禁止Spring的HibernateTemplate傳遞Proxy類,強制要求它傳遞真實的SessionImpl類,即給exexute方法增加一個參數,提供參數為true,如下:java代碼:public List findByCriteria(final DetachedCriteria detachedCriteria) {
return (List) getHibernateTemplate().execute(new HibernateCallback() {
public Object doInHibernate(Session session) throws HibernateException {
Criteria criteria = detachedCriteria.getExecutableCriteria(session);
return criteria.list();
}
}, true);
}
2. hibernate對SQL語句的使用
如下代碼:
(注意該類繼承自HibernateDaoSupport ,要在applicationContext.xml中將sessionFactory注入此類中)
public class DaoUtil extends HibernateDaoSupport {
public Object executeMySQL(final String sql){
System.out.println(sql);
return getHibernateTemplate().execute( new HibernateCallback(){
public Object doInHibernate(Session session)
throws HibernateException, SQLException {
Connection CurConn = session.connection();
PreparedStatement ps = CurConn.prepareStatement(sql);
ps.execute();
ps.close();
session.flush();
return null;
}
} );
}
public Object executeBetchSQL(final ArrayList sqlList){
return getHibernateTemplate().execute( new HibernateCallback(){
public Object doInHibernate(Session session)
throws HibernateException, SQLException {
Connection CurConn = session.connection();
int count = sqlList.size();
for(int i=0;i//System.out.println(sqlList.get(i));
PreparedStatement ps = CurConn.prepareStatement(sqlList.get(i));
ps.execute();
ps.close();
session.flush();
}
return null;
}
} );
}
public static DaoUtil getFromApplicationContext(
ApplicationContext ctx) {
return (DaoUtil) ctx.getBean("DaoUtil");
}
}
3. Hibernate中的SQL寫法。
我比較喜歡hibernate本身自帶的HQL語言,增刪改查語句基本不用自己寫。
添加:
Admin admin=new Admin();
admin.set...();
session.save(admin);
刪除:
session.delete(admin);
修改:
Admin admin=session.load(Admin.class,new Integer(i));
session.saveOrUpdate(admin);
查詢:
Query query = session.createQuery("select OBJECT(o) from Admin o order by o.adminid");
亦可寫成:
Query query = session.createQuery("from Admin");
注意:hibernate的業務邏輯操作必須放在事務中,代碼如下:
Transaction tr = session.beginTransaction();
try {
****增刪改查語句***
// 提交事務
tr.commit();
} catch (Exception e) {
// 回滾事務
tr.rollback();
} finally {
}
還有,hibernate內的語句不是SQL,而是HQL,但它支持SQL,又它特定的寫法;表名不是資料庫的名字,而是映射後的實體類(表)的名字;而且,是直接對資料庫進行操作,也就hibernate的事務一提交,資料庫內的信息就做了相應的修改;最後,hibernate不是個軟體,而是一個插件,通俗的說法是別人寫好的「包」,導入項目後,根據「包」的規范去做快速開發。
4. 如何用hibernate直接進行SQL語句查詢
String sql="SQL語句";session.createSqlQuery(sql);
5. 用hibernate 連接 sql server2000資料庫
主鍵是不能為空的,插入數據前要檢查該欄位值是否為空
6. 現在有個需求,用的是hibernate,需要在hibernate攔截器中對查詢的sql進行where條件拼接
這個寫起來很麻煩,提供解決思路。
1、在web.xml里實現攔截器配置。針對於某一個連接跳轉的。
2、攔截器功能實現,拿到參數。實現需要反射進行實現,同時要保證線程安全。
3、參數處理放到Session里。
4、在實際SQL語句中查詢。
如果跟spring集成的話,建議使用spring的AOP,進行動態代理實現。 進行初期處理。
7. 各位大俠,能不能幫忙吧下面的sql改寫成hibernate中可執行的語句。 我樣查最新的幾條數據hibernate語句。
額 hibernate支持sql語句...
public List<Menu> findMenusByEntityTypeId(Long id) {
String hql = "select m.id as {menu.id},m.name as {menu.name},m.url as {menu.url},m.icon_url as {menu.iconUrl},m.parent_id as {menu.parentId},"
+"m.serial_number as {menu.serialNo},m.admin as {menu.adminUse},m.system_admin as {menu.systemAdmin} ,m.program_name as {menu.programName}"
+" from menu m, entity_type et, entity_admin_menu eam"
+" where et.id = "+id+""
+" and m.program_name = '"+GlobalNames.PROGRAM_NAME_CHSS+"'"
+" and et.id = eam.entity_id"
+" and m.id = eam.menu_id";
List<Menu> menus = super.getSessionFactory().getCurrentSession().createSQLQuery(hql).addEntity("menu",Menu.class).list();
return menus;
}
所以說 你的sql直接hibernate就可以執行的
8. nhibernate是如何自動生成sql語句的
NHibernate 查看生成的sql語句:
其實就是Interceptor的應用, 源碼中Interceptor的默認實現是EmptyInterceptor,
[Serializable]
public class EmptyInterceptor : IInterceptor
{ //前面省略n行代碼
public SqlString OnPrepareStatement(SqlString sql)
{
return sql;
}
} public class MyInterceptor : EmptyInterceptor
{
public override NHibernate.SqlCommand.SqlString OnPrepareStatement(NHibernate.SqlCommand.SqlString sql)
{
return base.OnPrepareStatement(sql);
}
} 我們要做的就是繼承EmptyInterceptor,重寫OnPrepareStatement()方法,重寫方法裡面就是你大展拳腳的地方了,
想寫文件寫文件,想輸出到頁面就輸出到頁面,什麼都不做都可以,如上
怎麼用呢?
public override void Update(Admin entity)
{
ISession session = HibernateTemplate.SessionFactory.OpenSession(new MyIntercepotr);
session.Update(entity);
session.Flush();
}
在你想要查看的操作中,打開session 的時候添加上自定義的攔截器就可以了,想給所有的操作都配置的話就要用到全局配置文件了。
重寫OnPrepareStatement()的時候一句話都不改,我只是在這里打一個斷點而已,只要看看生成的sql語句就行了,然後去修改配置文件再來debug,確認怎麼配置生產的sql最優。
用LinqPad查看Nhibernate生成的sql語句
使用Nhibernate開發一般都要對Nhibernate生成的sql語句進行查看及分析,查看Nhibernate生成的sql語句,可以使用NHProfiler和log4net。但NHProfiler是要付費的(當然,在天朝,你懂的……),用log4net配置比較麻煩。今天在網上查看Linq to Nhibernate資料的時候發現了一個工具LinqPad,於是又找了相關資源,發現它還真能實現Nhibenate語句的查看。廢話少說,看下面的使用方法吧!
1、 下載LinqPad,地址:http://www.linqpad.net/
2、 配置LinqPad,運行LinqPad,在菜單里選擇Query—>Query Propeties;在選項卡中Additional References,點擊「Browse…」按鈕,選擇項目中必要的Dll。
Dll包括:資料庫驅動dll,實體映射dll(圖中的Entity),nhibernate相關的dll
9. HIBERNATE如何用SQL啊
Session session=getSession();
sql="insert into userRole(userID,roleID) values(?,?)
session.createSQLQuery(sql);