`
cfqlove
  • 浏览: 36712 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

运行期获取MyBatis执行的SQL及参数

 
阅读更多
public class MyBatisSqlUtils 
{
	/**
	 * 运行期获取MyBatis执行的SQL及参数
	 * @param id             Mapper xml 文件里的select Id
	 * @param parameterMap   参数
	 * @param sqlSessionFactory 
	 * @return
	 */
	public static MyBatisSql getMyBatisSql(String id, Map<String,Object> parameterMap,SqlSessionFactory sqlSessionFactory) {  
	    MyBatisSql ibatisSql = new MyBatisSql();  
	    MappedStatement ms = sqlSessionFactory.getConfiguration().getMappedStatement(id); 
	    BoundSql boundSql = ms.getBoundSql(parameterMap);  
	    ibatisSql.setSql(boundSql.getSql());  
	    List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();  
	    if (parameterMappings != null)
	    {  
	        Object[] parameterArray = new Object[parameterMappings.size()];
	        ParameterMapping parameterMapping = null;
	        Object value = null;  
	        Object parameterObject = null;
	        MetaObject metaObject = null;
	        PropertyTokenizer prop = null;
	        String propertyName = null;
	        String[] names = null;
	        for (int i = 0; i < parameterMappings.size(); i++) 
	        {  
	          parameterMapping = parameterMappings.get(i);  
	          if (parameterMapping.getMode() != ParameterMode.OUT) 
	          {  
	        	propertyName = parameterMapping.getProperty(); 
	        	names = propertyName.split("\\.");
	        	if(propertyName.indexOf(".") != -1 && names.length == 2)
	        	{
		        	parameterObject = parameterMap.get(names[0]);
	        		propertyName = names[1];
	        	}
	        	else if(propertyName.indexOf(".") != -1 && names.length == 3)
	        	{
	        		parameterObject = parameterMap.get(names[0]); // map
	        		if(parameterObject instanceof Map)
	        		{
	        			parameterObject = ((Map)parameterObject).get(names[1]);
	        		}
	        		propertyName = names[2];
	        	}
	        	else
	        	{
		        	parameterObject = parameterMap.get(propertyName);
	        	}
	            metaObject = parameterMap == null ? null : MetaObject.forObject(parameterObject);  
	            prop = new PropertyTokenizer(propertyName);  
	            if (parameterObject == null) 
	            {  
	              value = null;  
	            } 
	            else if (ms.getConfiguration().getTypeHandlerRegistry().hasTypeHandler(parameterObject.getClass())) 
	            {  
	              value = parameterObject;  
	            } 
	            else if (boundSql.hasAdditionalParameter(propertyName)) 
	            {  
	              value = boundSql.getAdditionalParameter(propertyName);  
	            } 
	            else if (propertyName.startsWith(ForEachSqlNode.ITEM_PREFIX) && boundSql.hasAdditionalParameter(prop.getName())) 
	            {  
	              value = boundSql.getAdditionalParameter(prop.getName());  
	              if (value != null) 
	              {  
	                value = MetaObject.forObject(value).getValue(propertyName.substring(prop.getName().length()));  
	              }  
	            } 
	            else 
	            {  
	              value = metaObject == null ? null : metaObject.getValue(propertyName);  
	            }  
	            parameterArray[i] = value;  
	          }  
	        }  
	        ibatisSql.setParameters(parameterArray);  
	    }  
	    return ibatisSql;  
	}


public class MyBatisSql 
{

	/**
	 * 运行期 sql
	 */
	private String sql;
	
	/**
	 * 参数 数组
	 */
    private Object[] parameters;
  
    public void setSql(String sql) {  
        this.sql = sql;  
    }  
  
    public String getSql() {  
        return sql;  
    }  
  
    public void setParameters(Object[] parameters) {  
        this.parameters = parameters;  
    }  
  
    public Object[] getParameters() {  
        return parameters;  
    }  
    
	@Override
	public String toString() {
		if(parameters == null || sql == null)
		{
			return "";
		}
		List<Object> parametersArray = Arrays.asList(parameters);
		List<Object> list = new ArrayList<Object>(parametersArray);
		while(sql.indexOf("?") != -1 && list.size() > 0 && parameters.length > 0)
		{
			sql = sql.replaceFirst("\\?", list.get(0).toString());
			list.remove(0);
		}
		return sql.replaceAll("(\r?\n(\\s*\r?\n)+)", "\r\n");
	}

以上贴的是实现代码,下面贴一段代码演示一下如何使用:

一、Mapper 文件
public interface AlarmMapper {

	public List<Alarm> queryAlarmData(@Param(value = "filter") Filter filter,
			@Param(value = "alarmStatus") AlarmStatus alarmStatus,
			@Param(value = "startDate") Date startDate,
			@Param(value = "endDate") Date endDate,
			@Param(value = "regionId") String regionId,
			@Param(value = "paramter") Map<String, Object> paramter,
			@Param(value = "startRow") int startRow,
			@Param(value = "endRow") int endRow) throws SQLException;
}


二、Mapper 的xml文件此处就不写了,select 的ID 为 queryAlarmData

三、在service层调用 queryAlarmData方法
public List<Alarm> queryAlarmData(Filter filter, AlarmStatus alarmStatus,
			Date start, Date end, String regionId, Map<String, Object> paramter,int startRow, int endRow) {
		try {
			List<Alarm> alarms = mapper.queryAlarmData(filter,
					alarmStatus, start, end, regionId,paramter, startRow, endRow);
			Map<String,Object> parameterMap = new HashMap<String,Object>(); //存储参数
			// key 要与Mapper中的参数名一致
			parameterMap.put("filter", filter);
			parameterMap.put("alarmStatus", alarmStatus);
			parameterMap.put("startDate", start);
			parameterMap.put("endDate", end);
			parameterMap.put("regionId", regionId);
			parameterMap.put("paramter", paramter);
			parameterMap.put("startRow", startRow);
			parameterMap.put("endRow", endRow);
			logger.info(MyBatisSqlUtils.getMyBatisSql("queryAlarmData", parameterMap, sqlSessionFactory).toString());
			return alarms;
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}


四、其实还可以用log4j来实现,将在下一篇博客贴出具体的实现代码(利用Spring的Aop以及自定义注解,实现系统日志功能)

五、欢迎各位指出本文的不妥之处,欢迎拍砖

分享到:
评论
5 楼 yqy563930552 2014-09-17  
	<select id="listByID" resultType="sql.entity.User" parameterType="java.util.List">
		SELECT
		<include refid="all_column" />
		FROM BAOFOO_ADMIN.admin_login_user
		WHERE user_id in
		<foreach collection="list" index="index" item="tag" open="(" separator="," close=")">
			#{tag}
		</foreach>
	</select>

当我的参数是个List对象的时候,我该怎么去sql和参数呢,,貌似博主的方法不管用了
4 楼 xuke6677 2013-09-23  
参数个数,类型不定,是从页面传过来的。我带的是map参数
3 楼 xuke6677 2013-09-23  
没有判断参数类型,拼接的sql无法执行。如下
select * from users where  username=张三  
请修正,求思路
2 楼 cfqlove 2012-06-05  
wufabeishang 写道
请问log4j怎么实现的啊?也能拦截到SQL执行的参数吗?


log4j.debug=true
log4j.rootLogger=INFO, stdout, alarmFile

# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p %d %C: %m%n

log4j.logger.org.junit=DEBUG
log4j.logger.junit=DEBUG

# ehcache logger config
log4j.logger.net.sf.ehcache=DEBUG

# ibatis logger config
log4j.logger.org.apache.mybatis=DEBUG
log4j.logger.java.sql.ResultSet=INFO
log4j.logger.java.sql=DEBUG


# alarm logger config
log4j.logger.com.boco.monitor.*=INFO, alarmFile
log4j.appender.alarmFile=org.apache.log4j.DailyRollingFileAppender
log4j.appender.alarmFile.File=${catalina.home}/alarm_logs/alarm_log.log
log4j.appender.alarmFile.layout=org.apache.log4j.PatternLayout
log4j.appender.alarmFile.layout.ConversionPattern=%5p %d %C: %m%n

# flex client logger config
log4j.logger.com.boco.monitor.flex.action.ClientLogger=DEBUG, clientLog
log4j.appender.clientLog=org.apache.log4j.DailyRollingFileAppender
log4j.appender.clientLog.File=${catalina.home}/client_logs/client_log.log
log4j.appender.clientLog.layout=org.apache.log4j.PatternLayout
log4j.appender.clientLog.layout.ConversionPattern=%5p %d %C: %m%n

这是我项目的log4j配置,你可以参考下。
1 楼 wufabeishang 2012-06-04  
请问log4j怎么实现的啊?也能拦截到SQL执行的参数吗?

相关推荐

    myBatis所有要用到的jar包

    8. **cglib**:Code Generation Library,是一个强大的高性能的代码生成库,用于在运行期扩展Java类与实现Java接口。MyBatis使用CGLib创建代理对象,以实现对Mapper接口的方法调用。 9. **ant**:Apache Ant是一个...

    mybatis-3.4.6.jar

    MyBatis避免了几乎所有的JDBC代码和手动设置参数以及获取结果集。MyBatis可以使用简单的XML或注解进行配置和原始映射,将接口和Java的POJOs(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录。 标题中...

    MyBatis真正的官方教程(来自官网)

    在执行SQL时,MyBatis支持多种参数映射方式,如简单类型、Map、POJO对象等。使用`@Param`注解可以为参数命名,避免参数顺序错误。 6. **结果映射** 结果映射用于将查询结果转换为Java对象。它可以自动处理一对一...

    MyBatis面试专题.docx

    通过CGLIB创建目标对象的代理,当调用关联属性时,代理对象会检查该属性是否已加载,若未加载则执行SQL获取关联数据。 **与Hibernate的差异**: MyBatis和Hibernate的主要区别在于,Hibernate提供更全面的自动化ORM...

    J2EE企业级项目开发-3期(KC007) 6.3 MyBatis的体系结构文档.doc

    - 为了提供稳定和高效的运行环境,MyBatis包含了几个关键的支撑机制: - **事务管理**:控制数据库事务的开始、提交和回滚。 - **连接池管理**:通过连接池提高数据库连接的复用性,减少创建和关闭连接的开销。 ...

    MyBatis完整jar包

    6. **cglib-3.2.4.jar**:CGlib是一个强大的、高性能的代码生成库,用于在运行期扩展Java类与实现Java接口。在MyBatis中,CGlib用于为没有接口的类创建代理,以便于实现MyBatis的动态SQL。 7. **ognl-3.1.12.jar**...

    SpringBoot+gradle+mybatis多数据源动态配置

    MyBatis避免了几乎所有的JDBC代码和手动设置参数以及获取结果集。在多数据源环境中,MyBatis可以帮助开发者更加灵活地处理数据库交互。 **多数据源** 多数据源是指在一个应用中同时连接和操作多个不同的数据库。...

    SpringMVC+Redis+MyBatis项目

    这时,Spring会检查是否有缓存策略存在,如果有且数据还在有效期内,直接从Redis中获取;否则,通过MyBatis查询数据库,将结果存储到Redis,并返回给客户端。后续相同请求可以直接从Redis缓存中获取数据,提升响应...

    mybatis-generator-core

    首先,MyBatis Generator (MBG) 是基于Java的,它通过读取数据库元数据,根据用户定义的模板生成MyBatis所需的SQL映射文件(Mapper XML)、Mapper接口和实体类(Entity)。这样,开发者无需手动编写这些基础代码,...

    spring+mybatis

    此版本改进了动态SQL的执行效率,增强了对Java 8日期时间API的支持,以及对XML配置和注解的增强。MyBatis 3.4在保持简洁的同时,提升了整体的使用体验和灵活性。 “mysql”代表MySQL数据库,这是一个流行的开源关系...

    spring+springmvc+mybatis搭建的一个湖北电信渠道营销支撑系统附带mysql数据库

    在本系统中,MyBatis作为数据库操作的接口,允许开发者直接编写SQL,从而提高了查询效率和灵活性,同时减少了因为ORM工具产生的性能损耗。 结合MySQL数据库,我们能有效地存储和管理电信渠道营销支撑系统中的大量...

    Spring框架,AOP,Spring整合Mybatis

    而CGLIB(Code Generation Library)是在运行期通过字节码技术动态生成子类来实现代理,即使目标对象没有实现接口也能进行代理。CGLIB在Spring框架中被广泛用于那些没有实现接口的类的代理。 Spring整合Mybatis是另...

    SpringMvc+MyBatis+ehcache+ExtJs分页

    通过配置Ehcache,我们可以设置缓存策略,如缓存有效期、大小限制等,确保系统的高效运行。 最后,ExtJS是一个强大的JavaScript前端框架,主要用于构建富客户端应用。它提供了一系列组件,如表格、表单、图表等,...

    (SSM)springmvc3.2+spring3.2+mybatis3.11(带jar包)

    - MyBatis 3.11版本则优化了SQL解析,增加了对Java 8日期时间API的支持,以及更丰富的日志功能。 通过提供的"jar包",开发者可以直接在MyEclipse这样的集成开发环境中导入,快速搭建SSM项目,省去了手动下载和配置...

    springboot+ MyBatis + Layui+Mysql医药WMS进销存源码

    MyBatis避免了几乎所有的JDBC代码和手动设置参数以及获取结果集。MyBatis可以使用简单的XML或注解进行配置和原始映射,将接口和Java的POJOs(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录。在本系统...

    springmvc4.1+spring4.1+mybatis3.2+spring-security3.2的maven环境搭建

    MyBatis 3.2引入了动态SQL、缓存优化和更好的错误消息,使得开发更加高效且易于调试。 **Spring Security 3.2** Spring Security是Spring生态系统中的安全组件,它提供了一套全面的认证和授权解决方案。Spring ...

    学习笔记动态SQL:Demo.zip

    CGLIB是一个强大的高性能的代码生成库,它在许多AOP框架中都得到了广泛应用,包括Spring AOP,它可以在运行期扩展Java类与实现Java接口。 CGLIB通过生成子类的方式实现对目标类的代理,而Javassist则可以直接修改...

    1+X考试真题-Java-中级-2021-11(1).docx

    试题解析:MyBatis 不会在运行期自动生成大量的 SQL 语句。MyBatis 的特点是将 SQL 语句封装在配置文件中,便于统一管理与维护,降低了程序的耦合度。 Spring 3. Spring 中的 @Autowired 和 @Resource 正确的是...

    ch10_User_MyBatis.rar

    【标题】"ch10_User_MyBatis.rar"是一个关于大三学生期末课程设计的项目,主要涉及用户管理系统。这个系统是用Java语言开发的,前端使用JSP(JavaServer Pages),后端数据库选用MySQL,整个开发环境可能基于...

    大学食堂人事管理系统 软件环境:intellij IDEA + maven + SpringBoot+ mybatis-plus

    Mybatis-Plus是Mybatis的增强工具,简化了常见的CRUD操作,如插入、更新、删除等,同时也提供了分页查询、动态SQL等功能,极大地提高了开发效率。在本系统中,Mybatis-Plus作为数据访问层,负责与数据库进行交互,...

Global site tag (gtag.js) - Google Analytics