版本:v2.0.0-beta1
本次对代码进行了彻底的重构,并调整了项目结构,项目命名为dexcoder-dal。
主要更新:
- 彻底的代码重写
- Criteria方式针对sql的api调整
- Criteria中支持sql函数的执行
- Criteria原生方式sql执行,
{}
完全原生,[]
进行fieldName到columnName转换的原生 - 支持执行自定义sql
- 支持使用类似mybatis的方式执行自定义sql
使用上来说变化主要有以下方面:
Criteria方式针对sql的api调整
针对不同的sql封装了不同的方法,对应sql的insert
、select
、update
、delete
,具体见下面代码:
Criteria.insert(User.class).into(...)
Criteria.select(User.class)...
Criteria.update(User.class).set(...)
Criteria.delete(User.class)...
Criteria中支持sql函数的执行
不再以简单的sql拼装的方式来完成想要的操作,提供了更好的扩展,执行函数便是其中之一,记录数count(*)
就使用了该方式:
//max()
Criteria criteria = Criteria.select(User.class).addSelectFunc("max([userId])");
Long userId = jdbcDao.queryForObject(criteria);
//count()
Criteria criteria = Criteria.select(User.class).addSelectFunc("count(*)");
Long count = jdbcDao.queryForObject(criteria);
//distinct
Criteria criteria = Criteria.select(User.class).addSelectFunc("distinct [loginName]");
List<Map<String, Object>> mapList = jdbcDao.queryForList(criteria);
默认情况下,addSelectFunc方法返回结果和表字段互斥,并且没有排序,如果需要和表其它字段一起返回并使用排序,可以使用如下代码:
Criteria criteria = Criteria.select(User.class).addSelectFunc("DATE_FORMAT(gmt_create,'%Y-%m-%d %h:%i:%s') date",false,true);
List<Map<String, Object>> mapList = jdbcDao.queryForList(criteria);
Criteria原生方式sql执行
在update和where条件中执行函数可以用{}
和[]
来实现:
Criteria criteria = Criteria.update(User.class).set("[userAge]", "[userAge]+1")
.where("userId", new Object[] { 56L });
jdbcDao.update(criteria);
以上代码将执行sql:UPDATE USER SET USER*AGE = USER*AGE+1 WHERE USER_ID = ?,[]中的fieldName被转换成了columnName,
也可以使用{}直接写columnName,因为在{}中的内容都是不做任何操作原生执行的,下面代码效果是一样的:
Criteria criteria = Criteria.update(User.class).set("{USER_AGE}", "{USER_AGE + 1}")
.where("userId", new Object[] { 56L });
jdbcDao.update(criteria);
同理,在where中也可以使用该方式来执行函数:
Criteria criteria = Criteria.select(User.class).where("[gmtCreate]", ">",
new Object[] { "str_to_date('2015-10-1','%Y-%m-%d')" });
List<User> userList = jdbcDao.queryList(criteria);
支持执行自定义sql
该方式可能会让除了dao层之外的业务层出现sql代码,因此是不推荐的,它适合一些不在项目中的情况。
何为不在项目中的情况?例如做一个开发自用的小工具,临时处理一批业务数据等这类后期不需要维护的代码。
要执行自定义sql首先需要在jdbcDao中注入sqlFactory,这里使用SimpleSqlFactory:
<bean id="jdbcDao" class="com.dexcoder.dal.spring.JdbcDaoImpl">
<property name="jdbcTemplate" ref="jdbcTemplate"/>
<property name="sqlFactory" ref="sqlFactory"/>
</bean>
<bean id="sqlFactory" class="com.dexcoder.dal.SimpleSqlFactory">
</bean>
然后就可以直接传入sql执行了:
List<Map<String, Object>> list = jdbcDao.queryForSql("select * from USER where login_name = ?",
new Object[] { "selfly_a99" });
这个实现比较简单,参数Object数组中不支持复杂的自定义对象。
使用类似mybatis的方式执行自定义sql
同样注入sqlFactory
,这里把上面的SimpleSqlFactory
替换成BatisSqlFactoryBean
:
<bean id="jdbcDao" class="com.dexcoder.dal.spring.JdbcDaoImpl">
<property name="jdbcTemplate" ref="jdbcTemplate"/>
<property name="sqlFactory" ref="sqlFactory"/>
</bean>
<bean id="sqlFactory" class="com.dexcoder.dal.batis.BatisSqlFactoryBean">
<property name="sqlLocation" value="user-sql.xml"/>
</bean>
BatisSqlFactoryBean
有一个sqlLocation
属性,指定自定义的sql文件,因为使用了spring的解析方式,所以可以和指定spring配置文件时一样使用各类通配符。
user-sql.xml
是一个和mybatis的mapper类似的xml文件:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//dexcoder.com//DTD Mapper 2.0//EN"
"http://www.ktanx.com/dtd/batis-mapper.dtd">
<mapper namespace="User">
<sql id="columns">
user_id,login_name,password,user_age,user_type
</sql>
<select id="getUser">
select
<include refid="columns"/>
from user
<where>
<if test="params[0] != null">
user_type = #{params[0].userType}
</if>
<if test="params[1] != null">
and login_name in
<foreach collection="params[1]" index="index" item="item" separator="," open="(" close=")">
#{item}
</foreach>
</if>
</where>
</select>
</mapper>
然后使用代码调用:
User user = new User();
user.setUserType("1");
Object[] names = new Object[] { "selfly_a93", "selfly_a94", "selfly_a95" };
List<Map<String, Object>> mapList = jdbcDao.queryForSql("User.getUser", "params", new Object[] { user, names });
for (Map<String, Object> map : mapList) {
System.out.println(map.get("userId"));
System.out.println(map.get("loginName"));
}
我们调用queryForSql
方法时传入了三个参数:
User.getUser
具体的sql全id,namespace+id。 params
自定义sql中访问参数的key,如果不传入默认为item。 Object[]
sql中用到的参数。访问具体参数时可以使用item[0],item[1]对应里面相应的元素,支持复杂对象。可以看到这里支持复杂参数,第一个是Userbean
对象,第二个是Object数组
,至于获取方式可以看上面的xml代码。
除了传入的参数为Object数组并使用item[0]
这种方式访问相应的元素外,其它的和mybatis可以说是一样的,mybatis支持的动态sql方式这里也可以支持,因为他本身就是来源于mybatis。
另外返回结果中map的key做了LOGIN_NAME
到骆驼命名法loginName
的转换。