通过Velocity模板实现了Hibernate sql-query的动态(SQL/HQL)

一.简介

    Hibernate对数据库结构提供了较为完整的封装,Hibernate的O/R Mapping实现了POJO 和数据库表之间的映射,以及SQL 的自动生成和执行。而MyBatis是一个支持普通SQL查询,存储过程和高级映射的优秀持久层框架,MyBatis需要使用简单的XML或注解用于配置和原始映射,将接口和Java的POJO(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录。在编写比较复杂的动态SQL语句时,Mybatis的SQL是手动编写的,所以可以按需求指定查询的字段,Hibernate就比较困难的实现。

二.解决问题的思路

   MyBatis支持普通SQL查询,存储过程和高级映射的优秀持久层框架,MyBatis需要使用XML配置,将接口和Java的POJO(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录,我们看一下MySql实现动态的SQL语句是什么样的,例如:




    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
  

  
  
    
      WHERE  1=1
       
          AND (T1.SFZH LIKE  '%'+#{param}+'%' OR T1.XM LIKE  '%'+#{param}+'%')
      
  
  


    resultMap 需要把一个一个字段配置,如果一个表字段太多了显示很臃肿也很容易配置出错,我们先抛开这个,我们来查看一下Mybatis怎么实现动态的sql的,采用了if、foreach 等标签,在执行SQL语句之前,先解析这些标签。

   我们在页面上也有采用模板引擎,内置了很多web编程中很常用的方法(日期转换、数字格式化等)方便开发人员操作。比较常见的是FreeMarker是模板引擎,是一种基于模板的、用来生成输出文本的通用工具,是基于Java的开发包和类库的。我们可以借鉴MyBatis实现思想和采用模板引擎。

   在给大家介绍另外一个Velocity,Velocity是一个基于java的模板引擎(templateengine)。它允许任何人仅仅简单的使用模板语言(template language)来引用由java代码定义的对象。它可以从模板(template)产生SQL和PostScript、XML,它也可以被当作一个独立工具来产生源代码和报告,或者作为其他系统的集成组件使用。Velocity也可以为Turbine web开发架构提供模板服务(template service)。

三.通过Velocity实现了sql-query动态sql

  1.先介绍工程的结构,这样思路会比较清晰

     通过Velocity模板实现了Hibernate sql-query的动态(SQL/HQL)_第1张图片



 2.实现hbm.xml的配置

    

 

 

    
        
            
        
        
        
        
        
        
        
        
        
    
    
      
       
        
        
      
      
      
    

   Velocity 是采用"#"用来标识的,例如#set、#if 、#else、#end、#foreach、#end、#iinclude、#parse、#macro等;

    例如:

     #if($xm)

         and t.xm=:xm

       #end

       #if($pch)

         and t.pch like '%$pch%'

       #end


 3.JAVA代码的实现

   

 (一)CardDaoImpl

    

@Repository
public class CardDaoImpl extends BaseDaoImpl implements CardDao {

	

	@SuppressWarnings("unchecked")
	@Override
	public List getCards(Map param) {
		return getNamedQuery("Card.getCards", param).setResultTransformer(Transformers.aliasToBean(Card.class)).list();
	}

}

 (二)BaseDaoImpl

       

public class BaseDaoImpl implements BaseDao {
	
	@Autowired
	private SessionFactory sessionFactory;

	public Session getCurrentSession() {
	    return sessionFactory.getCurrentSession();
	}

	@Override
	public void add(Object entriy) {
		getCurrentSession().save(entriy);
	}
	
	/**
	 * 设置动态的SQL
	 * @param queryName
	 * @param param
	 * @return
	 */
	@SuppressWarnings("rawtypes")
	public Query getNamedQuery(String queryName,Map  param ){
		Query query=getCurrentSession().getNamedQuery(queryName);
		Query rsQuery=null;
		try {
		//初始化运行时引擎, 默认初始化 
		Velocity.init();
		//建立context, 并放入数据
		VelocityContext context=new VelocityContext();
		Set keys=param.keySet();
		for (Iterator iterator = keys.iterator(); iterator.hasNext();) {
			String key = (String) iterator.next();
			context.put(key, param.get(key));
		}
		//解析后数据的输出目标,java.io.Writer的子类
		StringWriter sql=new StringWriter();
		//进行解析
		Velocity.evaluate(context, sql, "myQuery", query.getQueryString());
		rsQuery=getCurrentSession().createSQLQuery(sql.toString());
		} catch (Exception e) {
			e.printStackTrace();
		}
		setQueryNameParameters(rsQuery,param);
		return rsQuery;
		
	}
	
	/**
	 * 设置参数
	 * @param query
	 * @param param
	 * @return
	 */
	public Query setQueryNameParameters(Query query,Map  param){
		String[] nameParams=query.getNamedParameters();
		for(String nameParam:nameParams){
			Object obj=param.get(nameParam);
			if(obj instanceof Collection){
				query.setParameterList(nameParam, (Collection)obj);
			}else if(obj.getClass().isArray()){
				query.setParameterList(nameParam, (Object[])obj);
			}else{
				query.setParameter(nameParam,obj);
			}
			
		}
		
		return query;
		
	}

}


  是通过Velocity模板和传递进去的parameters参数对模板进行解析,得到最终的语句(纯sql/hql)。

  1)获取最原始的SQL语句Query query=getCurrentSession().getNamedQuery(queryName);

    通过Velocity模板实现了Hibernate sql-query的动态(SQL/HQL)_第2张图片

 2)通过Velocity模板和传递进去的parameters参数对模板进行对标签进行解析,Velocity.evaluate(context, sql, "myQuery", query.getQueryString());
通过Velocity模板实现了Hibernate sql-query的动态(SQL/HQL)_第3张图片

3)然后重新创建成sql/hql语句,rsQuery=getCurrentSession().createSQLQuery(sql.toString());

   通过Velocity模板实现了Hibernate sql-query的动态(SQL/HQL)_第4张图片

   4)设置参数值,执行返回结果

    通过Velocity模板实现了Hibernate sql-query的动态(SQL/HQL)_第5张图片











你可能感兴趣的:(Hibernate)