菜園子

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

          置頂隨筆 #

               摘要: 關于Hibernate的查詢從數據庫映射到JavaBean     Hibernate除了HQL外,還支持SQL的查詢,API為createSQLQuery(sql),如果數據庫使用的是Oracle,由于數據庫表中的列都是大寫,所以在從resultset到javabean的時候,需要完全匹配。 一般我們會用DTO或者作為DTO的Entity,無論是采用add...  閱讀全文
          posted @ 2014-08-27 15:08 GhostZhang 閱讀(10122) | 評論 (2)編輯 收藏

          升級Spring3.1RC2 和Hibernate4.0.0CR7遇到的一些問題及解決

          Spring3.1RC2支持

          1. Quartz2

          2. Hibernate4,

          3. New HandlerMethod-based Support Classes For Annotated Controller Processing

          4. Consumes and Produces @RequestMapping Conditions

          5. Working With URI Template Variables In Controller Methods

          6. Validation For @RequestBody Method Arguments  //and so on....

          7. Spring MVC 3.1 的annotation可以參看下http://starscream.iteye.com/blog/1098880 

          Hibernate 4可以查看http://community.jboss.org/wiki/HibernateCoreMigrationGuide40 

          下面主要說一下我在升級過程中遇到的一些問題及解決辦法。

          Maven的repository始終無法升級到SpringRC2,可能服務器有問題吧,目前暫時是從官方下載的整個SpringRC2的zip包。版本號是:3.1.0.RC2

          Hibernate可以從repository中升級到4.0.0.CR7,新增的依賴包有jandex-1.0.3.Final.jar,jboss-logging-3.1.0.CR2.jar,jboss-transaction-api_1.1_spec-1.0.0.Final.jar。

          Quartz升級到2.1.1,Ehcache-core升級到2.5.0

          Spring3.1取消了HibernateTemplate,因為Hibernate4的事務管理已經很好了,不用Spring再擴展了。所以以前的Dao需要改寫,直接調用Hibernate 的Session進行持久化。

          Spring的配置:

          sessionFactoryorg.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean換成org.springframework.orm.hibernate4.LocalSessionFactoryBean

          Spring的配置:

          <prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>改為

          <prop key="hibernate.cache.provider_class">net.sf.ehcache.hibernate.EhCacheProvider</prop>

          EhCacheRegionFactory使用配置:

          <prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop>

          使用Hibernate所有的openSession()改為getCurrentSession()

          Spring 的配置:Hibernate transactionManager從3改為4,如下:

          <bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">

                  <property name="sessionFactory" ref="sessionFactory"/>

              </bean>

          Spring @ResponseBody輸出是亂碼的問題:原來使用的是:

          <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">  

          改為:

          <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">  

          <property name = "messageConverters">

          <list>  

          <bean class = "org.springframework.http.converter.StringHttpMessageConverter">  

          <property name = "supportedMediaTypes">  

          <list>

          <value>text/plain;charset=UTF-8</value>

          </list>

          </property> 

          </bean>

          <bean class = "org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">  

          <property name = "supportedMediaTypes">  

          <list>

          <value>text/plain;charset=UTF-8</value>

          <value>application/json;charset=UTF-8</value>

          </list>  

          </property> 

          </bean>

          </list>  

          </property>  

          這樣比每個Controller都加上@RequestMapping(value = "/showLeft", method = RequestMethod.GET)
           produces = "text/plain; charset=utf-8"方便的多。

          Blob,以前配置:

          @TypeDefs({@TypeDef(name="clob",typeClass=ClobStringType.class),@TypeDef(name="blob",typeClass=BlobByteArrayType.class)})

          @Lob

          @Type(type="blob")

          public byte[] getPic() {

          return pic;

          }

          現在改為:

              @Lob

          public byte[] getPic() {

          return pic;

          }

          簡單很多。

           

          l 待續。。。

          posted @ 2011-12-13 15:36 GhostZhang 閱讀(3358) | 評論 (2)編輯 收藏

          Shiro權限框架

          開發系統中,少不了權限,目前java里的權限框架有SpringSecurity和Shiro(以前叫做jsecurity),對于SpringSecurity:功能太過強大以至于功能比較分散,使用起來也比較復雜,跟Spring結合的比較好。對于初學Spring Security者來說,曲線還是較大,需要深入學習其源碼和框架,配置起來也需要費比較大的力氣,擴展性也不是特別強。

          對于新秀Shiro來說,好評還是比較多的,使用起來比較簡單,功能也足夠強大,擴展性也較好。聽說連Spring的官方都不用Spring Security,用的是Shiro,足見Shiro的優秀。網上找到兩篇介紹:http://www.infoq.com/cn/articles/apache-shiro http://www.ibm.com/developerworks/cn/opensource/os-cn-shiro/,官網http://shiro.apache.org/ ,使用和配置起來還是比較簡單。下面只是簡單介紹下我們是如何配置和使用Shiro的(暫時只用到了Shiro的一部分,沒有配置shiro.ini文件)。

          首先是添加過濾器,在web.xml中:

          <filter>

          <filter-name>shiroFilter</filter-name>

          <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>

          <init-param>

                      <param-name>targetFilterLifecycle</param-name>

                      <param-value>true</param-value>

               </init-param>

          </filter>    

          <filter-mapping>

          <filter-name>shiroFilter</filter-name>

          <url-pattern>/*</url-pattern>

          </filter-mapping>

          權限的認證類:

          public class ShiroDbRealm extends AuthorizingRealm {

              @Inject

              private UserService userService ;

              

              /**

           * 認證回調函數,登錄時調用.

           */

          protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) 
          throws AuthenticationException {

          UsernamePasswordToken token = (UsernamePasswordToken) authcToken;

          User useruserService.getUserByUserId(token.getUsername());

          if (user!= null) {  

              return new SimpleAuthenticationInfo(user.getUserId(), user.getUserId(), getName());

          else {

          return null;

          }

          }

          /**

           * 授權查詢回調函數, 進行鑒權但緩存中無用戶的授權信息時調用.

           */

          protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {

          String loginName = (String) principals.fromRealm(getName()).iterator().next();

          User useruserService.getUserByUserId(loginName);

          if (user != null) {

          SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

          info.addStringPermission("common-user");

          return info;

          else {

          return null;

          }

          }

          }

          Spring的配置文件:

          <?xml version="1.0" encoding="UTF-8"?>

          <beans >

          <description>Shiro Configuration</description>

          <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"/>

          <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">

          <property name="realm" ref="shiroDbRealm" />

          </bean>

          <bean id="shiroDbRealm" class="com.company.service.common.shiro.ShiroDbRealm" />

              <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">

                  <property name="securityManager" ref="securityManager"/>

                  <property name="loginUrl" value="/common/security/login" />

                  <property name="successUrl" value="/common/security/welcome" />

                  <property name="unauthorizedUrl" value="/common/security/unauthorized"/>

                  <property name="filterChainDefinitions">

                      <value>

                          /resources/** = anon

                          /manageUsers = perms[user:manage]

                          /** = authc

                      </value>

                  </property>

              </bean>

          <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />

              <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor"/>

              <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">

                  <property name="securityManager" ref="securityManager"/>

              </bean>

          </beans>

          登錄的Controller:

          @Controller

          @RequestMapping(value = "/common/security/*")

          public class SecurityController {

              @Inject

              private UserService userService;

              @RequestMapping(value = "/login")

              public String login(String loginName, String password,
          HttpServletResponse response, HttpServletRequest request) throws Exception {

                  User user = userService.getUserByLogin(loginName);

                      if (null != user) {

                          setLogin(loginInfoVO.getUserId(), loginInfoVO.getUserId());

                          return "redirect:/common/security/welcome";

                      } else {

                          return "redirect:/common/path?path=showLogin";

                      }

              };

              public static final void setLogin(String userId, String password) {

                  Subject currentUser = SecurityUtils.getSubject();

                  if (!currentUser.isAuthenticated()) {

                      //collect user principals and credentials in a gui specific manner 

                      //such as username/password html form, X509 certificate, OpenID, etc.

                      //We'll use the username/password example here since it is the most common.

                      //(do you know what movie this is from? ;)

                      UsernamePasswordToken token = new UsernamePasswordToken(userId, password);

                      //this is all you have to do to support 'remember me' (no config - built in!):

                      token.setRememberMe(true);

                      currentUser.login(token);

                  }

              };

              

              @RequestMapping(value="/logout")

              @ResponseBody

              public void logout(HttpServletRequest request){

                  Subject subject = SecurityUtils.getSubject();

                  if (subject != null) {           

                      subject.logout();

                  }

                  request.getSession().invalidate();

              };

          }

          注冊和獲取當前登錄用戶:

              public static final void setCurrentUser(User user) {

                  Subject currentUser = SecurityUtils.getSubject();

                  if (null != currentUser) {

                      Session session = currentUser.getSession();

                      if (null != session) {

                          session.setAttribute(Constants.CURRENT_USER, user);

                      }

                  }

              };

              public static final User getCurrentUser() {

                  Subject currentUser = SecurityUtils.getSubject();

                  if (null != currentUser) {

                      Session session = currentUser.getSession();

                      if (null != session) {

                          User user = (User) session.getAttribute(Constants.CURRENT_USER);

                          if(null != user){

                              return user;

                          }

          }

          }

              };

          需要的jar包有3個:shiro-core.jar,shiro-spring.jar,shiro-web.jar。感覺shiro用起來比SpringSecurity簡單很多。

          posted @ 2011-09-16 21:36 GhostZhang 閱讀(32448) | 評論 (14)編輯 收藏

          在我們開發的一個系統中,有定時任務,自然就想到了Quartz,由于框架采用的Spring,Quartz跟Spring的集成也非常簡單,所以就把Quartz配置到框架中,當系統啟動后,定時任務也就自動啟動。在開發的過程中一直沒有發現問題,但是最后上線的時候,采用的是weblogic cluster,啟動了4個節點,發現有的定時任務執行了不止一次,才恍然大悟,4個節點啟動了4個應用,也就啟動了4個定時任務,所以在同一個時間定時任務執行了不止一次。去網上搜索,發現Quartz也支持cluster,但是我覺得就我們的系統而言,沒有必要采用cluster的定時任務,也許是比較懶吧,就想讓定時任務只執行一次。在網上搜到了robbin的一篇文章(http://robbin.iteye.com/blog/40989 ),發現把quartz集中到webapp當中還是有一定的風險,同時同一個時間點執行也不止一次。Robbin的解決辦法就是自己單獨啟動一個Job Server,來quartz跑job,不要部署在web容器中。 

          我也比較同意這個辦法。鑒于時間比較緊,就想有沒有比較方便的方法。其實把原來的webapp當做一個quartz的容器就可以了。可以自己寫一個線程來跑應用,再寫一個command啟動這個線程就可以了。線程類很簡單,如下:

          public class StartServer {

              public static void main(String[] args) throws Exception {

                  ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(
          new String[] { "/spring/context-annotation.xml","/spring/context-transaction.xml",
          "/spring/context-hibernate.xml",
          "/spring/context-quartz.xml"});

                  System.out.println("start server....");

                  while (true) {

                      try {

                          Thread.sleep(900);

                      } catch (InterruptedException ex) {

                      }

                  }

              };

          }

          去掉了系統的controller配置servlet.xml,運行這個類就可以了。

          在web-inf目錄下寫一個command來啟動這個java類:

          setlocal ENABLEDELAYEDEXPANSION

          if defined CLASSPATH (set CLASSPATH=%CLASSPATH%;.) else (set CLASSPATH=.)

          FOR /R .\lib %%G IN (*.jar) DO set CLASSPATH=!CLASSPATH!;%%G

          Echo The Classpath definition is==== %CLASSPATH%

          set CLASSPATH=./classes;%CLASSPATH%

          java com.company.job.StartServer

          這個command需要把需要的jar(web-inf/lib中)包都放到classpath中。

          每次啟動的時候執行這個command就可以了。跟原來的應用分開了,調試起定時任務也不用影響到原來的應用,還是比較方便的。部署的時候原樣拷貝一份,然后執行這個command就好了,部署起來也比較方便。

           

          posted @ 2011-09-13 12:53 GhostZhang 閱讀(2662) | 評論 (3)編輯 收藏

               摘要: Spring MVC經過三個版本,功能已經改進和完善了很多。尤其是2.5以來采用的Annotation的參數綁定,極大的方便了開發,3.0對其進行更進一步的完善。對于一些特殊的前臺框架,傳到后臺的不是普通的request中的參數,而是request流中的xml格式,這時就不能采用SpringMVC自帶的參數綁定方法。這時候考慮是否能擴展一下。SpringMVC默認使用的是Annotati...  閱讀全文
          posted @ 2011-09-12 19:12 GhostZhang 閱讀(4291) | 評論 (6)編輯 收藏

          接上一篇Hibernate 動態HQL(http://www.aygfsteel.com/ghostzhang/archive/2011/09/08/358320.html ),開發中經常需要修改SQL或者HQL的語句,但是每次都要重啟服務器才能使之起作用,就想到在使用Spring配置多語言時有一個ReloadableResourceBundleMessageSource.java類,可以配置動態加載多語言文件,為了配合動態HQL并實現修改HQL語句不用重啟服務器,可以參考下這個類的實現。Java代碼如下:(ReloadableDynamicHibernate.java)

            1 public class ReloadableDynamicHibernate{
            2     private final Map<String, XmlHolder> cachedXmls = new HashMap<String, XmlHolder>();
            3     private org.springframework.beans.factory.xml.DocumentLoader documentLoader = new org.springframework.beans.factory.xml.DefaultDocumentLoader();
            4     
            5     public void afterPropertiesSet() throws Exception {
            6         refreshLoad2Cache(true);
            7     };
            8 
            9     protected String getSqlByName(String queryKey) {
           10         refreshLoad2Cache(false);
           11         Collection<XmlHolder> xmlHolders = cachedXmls.values();
           12         for (XmlHolder holder : xmlHolders) {
           13             String qlString = holder.getQl(queryKey);
           14             if (StringUtils.isNotEmpty(qlString)) {
           15                 return qlString;
           16             }
           17         }
           18         throw new RuntimeException("can not find ql in xml.");
           19     };
           20 
           21     private void refreshLoad2Cache(boolean isForce) {
           22         for (int i = 0; i < fileNames.size(); i++) {
           23             String fileName = ((String) fileNames.get(i)).trim();
           24             if (resourceLoader instanceof ResourcePatternResolver) {
           25                 try {
           26                     Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(fileName);
           27                     for (Resource resource : resources) {
           28                         getXmls(resource,isForce);
           29                     }
           30                 } catch (IOException ex) {
           31                     throw new RuntimeException("Could not resolve sql definition resource pattern [" + fileName + "]", ex);
           32                 }
           33             } else {
           34                 Resource resource = resourceLoader.getResource(fileName);
           35                 getXmls(resource,isForce);
           36             }
           37         }
           38     };
           39 
           40     protected XmlHolder getXmls(Resource resource, boolean isForce) {
           41         synchronized (this.cachedXmls) {
           42             String filename = resource.getFilename();
           43             XmlHolder cachedXmls = this.cachedXmls.get(filename);
           44             if (cachedXmls != null && (cachedXmls.getRefreshTimestamp() < 0 || cachedXmls.getRefreshTimestamp() > System.currentTimeMillis())) {
           45                 return cachedXmls;
           46             }
           47             return refreshXmls(resource, cachedXmls, isForce);
           48         }
           49     };
           50 
           51     protected XmlHolder refreshXmls(Resource resource, XmlHolder xmlHolder, boolean isForce) {
           52         String filename = resource.getFilename();
           53         long refreshTimestamp = System.currentTimeMillis();
           54         if (resource.exists()) {
           55             long fileTimestamp = -1;
           56             try {
           57                 fileTimestamp = resource.lastModified();
           58                 if (!isForce && xmlHolder != null && xmlHolder.getFileTimestamp() == fileTimestamp) {
           59                     if (LOGGER.isDebugEnabled()) {
           60                         LOGGER.debug("Re-caching properties for filename [" + filename + "] - file hasn't been modified");
           61                     }
           62                     xmlHolder.setRefreshTimestamp(refreshTimestamp);
           63                     return xmlHolder;
           64                 }
           65             } catch (IOException ex) {
           66                 if (LOGGER.isDebugEnabled()) {
           67                     LOGGER.debug(resource + " could not be resolved in the file system - assuming that is hasn't changed", ex);
           68                 }
           69                 fileTimestamp = -1;
           70             }
           71             try {
           72                 Map qlMap = loadQlMap(resource);
           73                 xmlHolder = new XmlHolder(qlMap, fileTimestamp);
           74             } catch (Exception ex) {
           75                 if (LOGGER.isWarnEnabled()) {
           76                     LOGGER.warn("Could not parse properties file [" + resource.getFilename() + "]", ex);
           77                 }
           78                 xmlHolder = new XmlHolder();
           79             }
           80         } else {
           81             if (LOGGER.isDebugEnabled()) {
           82                 LOGGER.debug("No properties file found for [" + filename + "] - neither plain properties nor XML");
           83             }
           84             xmlHolder = new XmlHolder();
           85         }
           86         xmlHolder.setRefreshTimestamp(refreshTimestamp);
           87         this.cachedXmls.put(filename, xmlHolder);
           88         return xmlHolder;
           89     };
           90 
           91     protected Map<String,String> buildHQLMap(Resource resource) throws Exception {
           92         Map<String, String> qlMap = new HashMap<String, String>();
           93         try {
           94             InputSource inputSource = new InputSource(resource.getInputStream());
           95             org.w3c.dom.Document doc = this.documentLoader.loadDocument(inputSource, nullnull, org.springframework.util.xml.XmlValidationModeDetector.VALIDATION_NONE, false);
           96             Element root = doc.getDocumentElement();
           97             List<Element> querys = DomUtils.getChildElements(root);
           98             for(Element query:querys){
           99                 String queryName = query.getAttribute("name");
          100                 if (StringUtils.isEmpty(queryName)) {
          101                     throw new Exception("DynamicHibernate Service : name is essential attribute in a <query>.");
          102                 }
          103                 if(qlMap.containsKey(queryName)){
          104                     throw new Exception("DynamicHibernate Service : duplicated query in a <query>.");
          105                 }
          106                 qlMap.put(queryName, DomUtils.getTextValue(query));
          107             }
          108         } catch (Exception ioe) {
          109             throw ioe;
          110         }
          111         return qlMap;
          112     };
          113 
          114     protected Map loadQlMap(Resource resource) {
          115         Map qlMap = new HashMap<String, String>();
          116         InputStream is = null;
          117         try {
          118             is = resource.getInputStream();
          119             return buildHQLMap(resource);
          120         } catch (Exception e) {
          121             e.printStackTrace();
          122         } finally {
          123             try {
          124                 if (null != is) {
          125                     is.close();
          126                 }
          127             } catch (Exception e) {
          128                 e.printStackTrace();
          129             }
          130         }
          131         return qlMap;
          132     };
          133 
          134     protected class XmlHolder {
          135         private Map<String, String> qlMap;                //查詢的映射
          136         private long                fileTimestamp    = -1;
          137         private long                refreshTimestamp = -1;
          138         public String getQl(String key) {
          139             if (null != qlMap) {
          140                 return qlMap.get(key);
          141             } else {
          142                 if (LOGGER.isErrorEnabled()) {
          143                     LOGGER.debug("error is occured in getQl.");
          144                 }
          145                 return "";
          146             }
          147         }
          148 
          149         public XmlHolder(Map<String, String> qlMap, long fileTimestamp) {
          150             this.qlMap = qlMap;
          151             this.fileTimestamp = fileTimestamp;
          152         }
          153         public XmlHolder() {
          154         }
          155         public Map<String, String> getQlMap() {
          156             return qlMap;
          157         }
          158         public long getFileTimestamp() {
          159             return fileTimestamp;
          160         }
          161         public void setRefreshTimestamp(long refreshTimestamp) {
          162             this.refreshTimestamp = refreshTimestamp;
          163         }
          164         public long getRefreshTimestamp() {
          165             return refreshTimestamp;
          166         }
          167     }
          168 }        

          Spring 配置如下:


          <bean id="dynamicHibernate" class="com.company.ReloadableDynamicHibernate">
                  <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>

          這樣就實現了每次修改SQL or HQL語句后不用重啟服務器,立刻看到結果,加快了開發速度。

           

           

          posted @ 2011-09-10 12:25 GhostZhang 閱讀(2379) | 評論 (3)編輯 收藏

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

          這個時候就想到了模板語言和配置文件的結合。模板引擎可以選擇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>

           

          在系統加載時,需要把配置文件加載到系統中。加載代碼關鍵部分如下:

           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>

          下一步是在使用時調用sql并調用模板方法,進行sql動態化。

          還是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

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

          僅列出標題  
          主站蜘蛛池模板: 潞城市| 佛冈县| 静海县| 镇远县| 油尖旺区| 龙泉市| 江山市| 上饶县| 镇巴县| 公主岭市| 沁阳市| 屏山县| 兴海县| 彭阳县| 冀州市| 井陉县| 都安| 海晏县| 阳山县| 龙海市| 武汉市| 木兰县| 宣化县| 拉萨市| 巫溪县| 伊春市| 梓潼县| 景东| 新安县| 印江| 永新县| 威信县| 伊金霍洛旗| 延寿县| 郯城县| 鄯善县| 台南市| 武川县| 榆社县| 北京市| 贡山|