菜園子

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

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

          這個(gè)時(shí)候就想到了模板語(yǔ)言和配置文件的結(jié)合。模板引擎可以選擇Velocity,簡(jiǎn)單而不失強(qiáng)大,配置文件可以模仿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)加載時(shí),需要把配置文件加載到系統(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>

          下一步是在使用時(shí)調(diào)用sql并調(diào)用模板方法,進(jìn)行sql動(dòng)態(tài)化。

          還是DynamicHibernateImpl這個(gè)類 

           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 閱讀(3452) 評(píng)論(2)  編輯  收藏

          Feedback

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

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


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


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 定日县| 来凤县| 潢川县| 望都县| 杂多县| 罗田县| 名山县| 扎鲁特旗| 仁化县| 竹北市| 奉化市| 宁化县| 五原县| 墨玉县| 县级市| 盐源县| 共和县| 方城县| 彭泽县| 班玛县| 大埔县| 太保市| 高陵县| 武义县| 喀喇| 石棉县| 广平县| 临湘市| 景宁| 临海市| 镇雄县| 法库县| 德保县| 剑河县| 微山县| 固镇县| 平顺县| 汪清县| 香河县| 吴忠市| 宁强县|