利用 association 解决多对一、一对一问题时,在配置 resultMap 时使用 autoMapping 属性映射表字段时,生成的多端对象数据中是拿不到声明的外键的。 如果业务有需要在多的一端对象中直接获取外键属性,而不是通过对应的一端来获取,那么就需要在使用 autoMapping 时,重新为多端表指明主外键映射关系或者撇弃 autoMapping 而改用手工声明。 首先做如下定义:

阅读全文......

最近的项目中使用到了mybatis,发现mybatis不支持物理分页,只支持内存分页。因此为了解决这个问题,在网上搜索了一番,不过都比较繁琐。最后使用正则表达过滤查询语句的方式简单解决了该问题. mybatis物理分页的核心是使用mybatis的拦截器 org.apache.ibatis.plugin.Interceptor ,在mybatis准备好SQL的时候,对SQL字符串进行拦截,生成适合Oracle数据库的分页语句即可。废话不多讲了,直接上代码.
Note: 该部分依赖commons-lang3.jar包进行反射写入,也可使用 mybatis 自带的反射类实现这部分功能

拦截器代码

package org.mybatis.test.interceptor;

import java.sql.Connection;
import java.util.*;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.session.RowBounds;

@Intercepts(@Signature(type = StatementHandler.class, method = "prepare", args = { Connection.class }))
public class PaginationInterceptor implements Interceptor {

	private final static String SQL_SELECT_REGEX = "(?is)^\\s*SELECT.*$";
	private final static String SQL_COUNT_REGEX = "(?is)^\\s*SELECT\\s+COUNT\\s*\\(\\s*(?:\\*|\\w+)\\s*\\).*$";

	//@Override
	public Object intercept(Invocation inv) throws Throwable {

		StatementHandler target = (StatementHandler) inv.getTarget();

		BoundSql boundSql = target.getBoundSql();

		String sql = boundSql.getSql();

		if (StringUtils.isBlank(sql)) {
			return inv.proceed();
		}
		System.out.println("origin sql>>>>>" + sql.replaceAll("\n", ""));

		// 只有为select查询语句时才进行下一步
		if (sql.matches(SQL_SELECT_REGEX)
				&& !Pattern.matches(SQL_COUNT_REGEX, sql)) {

			Object obj = FieldUtils.readField(target, "delegate", true);
			// 反射获取 RowBounds 对象。
			RowBounds rowBounds = (RowBounds) FieldUtils.readField(obj,
					"rowBounds", true);
					
			// 分页参数存在且不为默认值时进行分页SQL构造
			if (rowBounds != null && rowBounds != RowBounds.DEFAULT) {
				FieldUtils.writeField(boundSql, "sql", newSql(sql, rowBounds),
						true);
				System.out.println("new sql>>>>>"
						+ boundSql.getSql().replaceAll("\n", ""));

				// 一定要还原否则将无法得到下一组数据(第一次的数据被缓存了)
				FieldUtils.writeField(rowBounds, "offset",
						RowBounds.NO_ROW_OFFSET, true);
				FieldUtils.writeField(rowBounds, "limit",
						RowBounds.NO_ROW_LIMIT, true);
			}
		}
		return inv.proceed();
	}

	public String newSql(String oldSql, RowBounds rowBounds) {
		String start = " SELECT * FROM   (SELECT   row_.*, ROWNUM rownum_ FROM ( ";
		String end = " ) row_ WHERE   ROWNUM <= " + rowBounds.getLimit()
				+ ") WHERE   rownum_ > " + rowBounds.getOffset();

		return start + oldSql + end;
	}

	//@Override
	public Object plugin(Object target) {
		return Plugin.wrap(target, this);
	}

	//@Override
	public void setProperties(Properties arg0) {
		System.out.println(arg0);
	}
    
    //测试正则表达式是否能正常工作
	public static void main(String[] args) {
		String SQL_SELECT_REGEX = "^\\s*SELECT.*$";
		String SQL_COUNT_REGEX = "^\\s*SELECT\\s+COUNT\\s*\\(\\s*(?:\\*|\\w+)\\s*\\).*$";
		List<String> tests = new ArrayList<String>();
		tests.add("select count(*) from abc \n\t\t where\n abc");
		tests.add("SELECT 	COUNT(*) from abc");
		tests.add(" select count  (*) from abc");
		tests.add("  select count(  *) from abc");
		tests.add("select count( *  ),id   from abc");
		tests.add("select * from abc");
		tests.add("select abc,test,fdas from abc");
		tests.add("select count(adb) from abc");
		tests.add("select count(0) from abc");
		tests.add("select min(count(*)) from abc");
		tests.add("update min(count(*)) from abc");
		tests.add("delete min(count(*)) from abc");
		Pattern p1 = Pattern.compile(SQL_SELECT_REGEX, Pattern.DOTALL
				| Pattern.CASE_INSENSITIVE);
		Pattern p2 = Pattern.compile(SQL_COUNT_REGEX, Pattern.DOTALL
				| Pattern.CASE_INSENSITIVE);
		for (String str : tests) {
			Matcher m1 = p1.matcher(str);
			Matcher m2 = p2.matcher(str);
			System.out.println("匹配字符串: " + str);
			System.out.println("	是select语句? " + m1.matches());
			System.out.println("	是count语句? " + m2.matches());
			System.out.println();
		}
	}
}

在spring中配置拦截器

<bean name="paginationInterceptor" class="org.mybatis.test.interceptor.PaginationInterceptor"></bean>

<!-- define the SqlSessionFactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
	<property name="dataSource" ref="dataSource" />
	<property name="typeAliasesPackage" value="org.mybatis.test.domain" />
	<property name="plugins">
		<list>
			<ref bean="paginationInterceptor" />
		</list>
	</property>
</bean>

使用

public class Test(){
	private String name;
	private int age;
	// set/get省
}
  1. 阅读全文......

null表示无值或不存在的对象;
  • undefined表示一个未声明的变量。声明但没有赋值的变量或者一个并不存在的对象属性;
     var param; // 声明但不赋值,其等价于
     var param = undefined;
    
     var obj = {}; //声明一个对象
     var param1 = obj.param; // 对象不存在的属性
     console.info(param1); // undefined
     console.info(param1 === undefined); // true
    
  • undefined不同于未定义,但在使用typeof方法时,该方法并不区分undefined未定义,其返回值均为字符串undefined
     var param; 
     console.info(typeof param); // 打印 "undefined"
     console.info(typeof param === 'undefined'); // true
    
     // 注意:param1并未被声明,属于首次使用
     console.info(typeof param1); // 打印 "undefined"
     console.info(typeof param1 === 'undefined'); // true
    
  • 阅读全文......

  • 原文地址:http://docs.jquery.com/Plugins/Authoring So you’ve become comfortable with jQuery and would like to learn how to write your own plugins. Great! You’re in the right spot. Extending jQuery with plugins and methods is very powerful and can save you and your peers a lot of development time by abstracting your most clever functions into plugins. This post will outline the basics, best practices, and common pitfalls to watch out for as you begin writing your plugin. 当你已经熟练掌握jQuery并且想学习如何编写属于自己的插件程序时,你可以参看这篇文章。使用插件程序和方法扩展jQuery是非常强大的。你可以将一些想法抽象为函数并封装到插件中以便为你和你的同事节省许多开发时间。

    目录(CONTENTS)

    1. 阅读全文......

    当参数未使用@Param注解时,可以通过以下方式访问:
    #{参数位置[0..n-1]}
    或者

    阅读全文......

    很多时候我们需要对页面上的表格进行添加一行,删除一行这样的基本操作。如果我们使用原生的javascrip来写会很不方便。为了解决这个问题我们封装了一些常规的页面表格处理方式,集成到jQuery中,方面我们后续使用。 如此,jQuery eTable Plugin 便应运而生了。该套函数库提供对表格操作的一些基本方法。其实质是通过$(table).eTable()获取封装了表格元素的ETable对象,同时.eTable对象封装了一些列针对表格行列进行操作的方法。使用这些方法可以对表格进行行列的插入与删除。 可以通过如下方式获取页面表格对象:
    var $eTable = $("#table1").eTable();
    var $eTable = $(document.getElementById('table1')).eTable();
    

    阅读全文......

    移动目标元素对象,使其显示在遮罩层正中央。 jmask 接受一个参数.
    options: 该参数为对象类型。用来设置遮罩层默认全局属性,默认属性为:
    $.fn.jmask.defaults = {
    	bgcolor : '#eee',
    	opacity : 0.8
    };
    
    Example:
    $("#jmaskDemo").jmask();
    $("#jmaskDemo").jmask({
        bgcolor:'pink',
        opacity : 0.6
    });
    

    junmask() 关闭遮罩层

    阅读全文......

    abs(n) : 返回n的绝对值 ceil(n) : 返回大于等于数字n的最小整数 floor(n) : 返回小于等于数字n的最大整数

    阅读全文......

    内连接用于返回满足连接条件的所有记录;默认情况下,在执行连接查询时如果没有指定任何连接操作符,那么这些连接查询都属于内连接。
    SQL> select a.dname,b.ename from department a, employee b where a.deptNo = b.deptNo;
    
    或者
    SQL> select a.dame,b.ename from department a inner join employee b ON a.deptNo = b.deptNo;
    
    NOTES:

    阅读全文......

    grouping : 用于确定统计结果是否用到了特定列。如果返回0,则表示统计结果使用了该列;如果返回1,则表示统计结果未使用该列
     SQL> SELECT name,address ,SUM(money),GROUPING(name),GROUPING(address) FROM customer GROUP BY CUBE(name,address);
     NAME                         ADDRESS  COUNT(*) SUM(MONEY) GROUPING(name)  GROUPING(address)
     ---------------------------- ------- ---------- --------- --------------  -----------------
                                             4		162.26		1				1
                                 a		 	1		32			1				0
                                 abcdefg		2		118.03		1				0
                                 152号大街	1		12.23		1				0
     oxcow									2		118.03		0				1
     oxcow						abcdefg		2		118.03		0				0
     leeyee									2		44.23		0				1
     leeyee						a			1		32			0				0
     leeyee						152号大街	1		12.23		0				0
    
  • dense_rank(expr1,expr2,..) within group (order by expr1,expr2,..) : 该函数用于返回特定数据在一组行数据中的等级。关于rank,dense_rank的具体说明请查看
     SQL> select dense_rank(5000) within group (order by sal) rank from emp;
             RANK
             -----
             12
    
  • first : Oracle9i新增函数,获取首个排序等级,然后使用分组汇总函数汇总。该函数不能单独使用,必须与其他分组函数结合使用
     -- 年龄最大的一组人中工资最高的
     SQL> select max(money) keep (dense_rank first order by age desc) from customer;
    
  • 阅读全文......