菜園子

          BlogJava 首頁 新隨筆 聯(lián)系 聚合 管理
            7 Posts :: 1 Stories :: 31 Comments :: 0 Trackbacks

          在開發(fā)的時候,很多時候都遇到過需要動態(tài)拼寫SQL,有的是在配置文件中寫SQL,有的是在Java代碼中拼寫SQL,以配置文件拼SQL的可以拿IBatis為代表,但是很多時候是使用Hibernate的,這個時候就想要是Hibernate能像IBatis那樣寫就好了。

          這個時候就想到了模板語言和配置文件的結(jié)合。模板引擎可以選擇Velocity,簡單而不失強大,配置文件可以模仿Hibernate的sql-query 的XML文件。

          Sq-query的示例代碼如下(SQL or HQL):

          <?xml version="1.0" encoding="UTF-8"?>
          <!DOCTYPE dynamic-hibernate PUBLIC "-//ANYFRAME//DTD DYNAMIC-HIBERNATE//EN"
          "http://www.anyframejava.org/dtd/anyframe-dynamic-hibernate-mapping-4.0.dtd">
          <dynamic-hibernate>
              <query name="selectUserSQL">
                  <![CDATA[
                      SELECT  USER_ID,NAME
                      FROM users_table Where 1=1
                      #if($name && $name.length() > 1)
                       AND name =:name
                      #end
              ]]>
              </query>
              <query name="selectUserHQL">
              <![CDATA[
                   FROM users
                  Where 1=1
                      #if($name && $name.length() > 1)
                          AND name =:name
                      #end
                  ]]>
              </query>

           

          在系統(tǒng)加載時,需要把配置文件加載到系統(tǒng)中。加載代碼關(guān)鍵部分如下:

           1   public class DynamicHibernateImpl implements InitializingBean, ResourceLoaderAware, ApplicationContextAware
           
           
           2       public void afterPropertiesSet() throws Exception {
           3          for (int i = 0; i < fileNames.size(); i++) {
           4             String fileName = ((String) fileNames.get(i)).trim();
           5             if (resourceLoader instanceof ResourcePatternResolver) {                
           6                 try {
           7                     Resource[] resources=((ResourcePatternResolver) resourceLoader).getResources(fileName);
           8                   buildHQLMap(resources);
           9                 } catch (IOException ex) {
          10                     throw new Exception("Could not resolve sql definition resource pattern [" + fileName + "]", ex);
          11                 }
          12             } else {               
          13                 Resource resource = resourceLoader.getResource(fileName);
          14                 buildHQLMap(new Resource[] { resource });
          15             }
          16         }
          17     }
          18  protected void buildHQLMap(Resource[] resources) throws Exception {
          19         for (int i = 0; i < resources.length; i++) {
          20             buildHQLMap(resources[i]);
          21         }
          22     }
          23  private void buildHQLMap(Resource resource) throws Exception {
          24         try {
          25             InputSource inputSource = new InputSource(resource.getInputStream());
          26             org.w3c.dom.Document doc = this.documentLoader.loadDocument(inputSource, nullnull, org.springframework.util.xml.XmlValidationModeDetector.VALIDATION_NONE, false);
          27             Element root = doc.getDocumentElement();
          28             List<Element> querys = DomUtils.getChildElements(root);
          29             for(Element query:querys){
          30                 String queryName = query.getAttribute("name");
          31                 if (StringUtils.isEmpty(queryName)) {
          32                     throw new Exception("DynamicHibernate Service : name is essential attribute in a <query>.");
          33                 }
          34                 if(statements.containsKey(queryName)){
          35                     throw new Exception("DynamicHibernate Service : duplicated query in a <query>."+queryName);
          36                 }
          37                 statements.put(queryName, DomUtils.getTextValue(query));
          38             }
          39         } catch (SAXParseException se) {
          40             throw se;
          41         } catch (IOException ioe) {
          42             throw ioe;
          43         }
          44     }

          Spring的配置文件示例如下:

          <bean id="dynamicHibernate" class="com.company.DynamicHibernateImpl">
          <property name="sessionFactory" ref="sessionFactory" />
          <property name="simpleTemplate" ref="simpleTemplate" />
          <property name="fileNames">
          <list>
          <value>classpath*:hibernate/dynamic/dynamic-hibernate-*.xml</value>
          </list>
          </property>
          </bean>

          下一步是在使用時調(diào)用sql并調(diào)用模板方法,進行sql動態(tài)化。

          還是DynamicHibernateImpl這個類 

           1     public List findList(String queryName, Map params, int pageIndex, int pageSize) throws Exception { 
           2
                   Context context = generateVelocityContext(params);
           3         Query query = findInternal(queryName, context);
           4         if (pageIndex > 0 && pageSize > 0) {
           5             query.setFirstResult((pageIndex - 1) * pageSize);
           6             query.setMaxResults(pageSize);
           7         }
           8       return query.list();        
           9     };
          10   private Context generateVelocityContext(Map<String, Object> params) {
          11         VelocityContext context = new VelocityContext();
          12         if (null == params) {
          13             return null;
          14         }
          15         Iterator<String> iterator = params.keySet().iterator();
          16         while (iterator.hasNext()) {
          17             String key = iterator.next();
          18             Object value = params.get(key);
          19             if (null == value) {
          20                 continue;
          21             }           
          22             context.put(key, value);
          23         }
          24         return context;
          25     };
          26  private Query findInternal(String queryName, Context context) throws Exception {
          27         String sql = findSQLByVelocity(queryName, context);
          28         Query query = sessionFactory.getCurrentSession().createQuery(sql);
          29         String[] namedParams = query.getNamedParameters();
          30         setProperties(query, context, namedParams);
          31         return query;
          32     };
          33  private String findSQLByVelocity(String queryName, Context context) throws Exception {
          34         if (context == null)
          35             context = new VelocityContext();
          36         String sql = getSqlByName(queryName);
          37         StringWriter writer = new StringWriter();
          38         Velocity.evaluate(context, writer, "Hibernate", sql);
          39         sql = writer.toString();
          40         return sql;
          41     };
          42 protected String getSqlByName(String queryKey) {
          43         return statements.get(queryKey);
          44     }

          就這些。

          大家也許有更好的方法,歡迎交流。

          QQ:24889356



          QQ:24889356
          posted on 2011-09-08 19:14 GhostZhang 閱讀(3451) 評論(2)  編輯  收藏

          Feedback

          # re: Hibernate 動態(tài) HQL 2011-09-09 08:17 tb
          恩 不錯 很好啊   回復(fù)  更多評論
            

          # re: Hibernate 動態(tài) HQL 2011-09-09 09:16 唐山訂餐網(wǎng)
          太棒了 博主真是高人  回復(fù)  更多評論
            


          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 乐平市| 赤壁市| 青川县| 徐州市| 高清| 平顶山市| 南昌县| 松潘县| 北宁市| 英德市| 泽库县| 黔西| 北川| 孟连| 铁岭市| 曲周县| 顺义区| 武功县| 西峡县| 鄄城县| 呼和浩特市| 漳州市| 辰溪县| 确山县| 叶城县| 双柏县| 炎陵县| 卓资县| 叙永县| 家居| 武穴市| 隆林| 桓台县| 肃南| 宝坻区| 宁陵县| 青岛市| 怀化市| 宁明县| 湛江市| 宜春市|