Spring JdbcTemplate实现通用的超级dao,比泛型dao更加强大(续)

分类: Spring 3人评论 selfly 1年前发布

前面介绍了一些基本方法的使用,除了不用一个实体类对应的dao外没多大区别,接下来介绍的就是本次改进的重点了。

封装完成之后,用这个通用dao做了个小站,在使用过程中,速度提升不少,但是还有些小细节不够完美,目前感受到的有以下:

1、一个字段等于多个值的or方式查询实现了,但是多个字段还没法使用or。

2、不new实体对象查询时,支持列表,但不支持查询记录数(count)。

3、方法重载的问题,比如where和whereAssign方法,因为参数使用了jdk的...多参数方法,所以两个方法如果同名会出现问题,不同名则使用起来多有不便。

目前就只有以上三个,会在后期改进,在这里介绍的是还没有改进之前的,毕竟总的思路没有变,旨在抛砖引玉,给个参考。

不new实体对象,直接查询

查询目前只支持返回List,代码如下,上面是执行对应的sql:

//[SELECT GMT_CREATE,GMT_MODIFY,USER_AGE,USER_ID,USER_NAME FROM USER WHERE USER_ID = ? ORDER BY USER_ID DESC]
List<User> users = superDao.where("userId", 1L).query(User.class);
//[SELECT GMT_CREATE,GMT_MODIFY,USER_AGE,USER_ID,USER_NAME FROM USER WHERE (USER_ID = ? OR USER_ID = ? OR USER_ID = ?) ORDER BY USER_ID DESC]
List<User> users1 = superDao.where("userId", 1L, 2L, 3L).query(User.class);
//[SELECT GMT_CREATE,GMT_MODIFY,USER_AGE,USER_ID,USER_NAME FROM USER WHERE USER_ID < ? ORDER BY USER_ID DESC]
List<User> users2 = superDao.whereAssign("userId", "<", 3).query(User.class);

不new实体对象,直接更新

直接更新为了避免不小心更新全表的情况,所以必须要有where条件:

//[UPDATE USER SET USER_NAME = ? WHERE USER_ID = ?]
superDao.set("userName", "selfly").where("userId", 1L).update(User.class);

白名单

白名单功能指定要返回的字段,其它字段将被忽略,该功能在当你的表中有大字段时非常有用,可以和查询两个方法一起使用,下面的代码最终执行的sql是一样的:

//[SELECT USER_ID FROM USER WHERE USER_ID = ? ORDER BY USER_ID DESC]
List<User> users = superDao.include("userId").where("userId",1L).query(User.class);
//[SELECT USER_ID FROM USER WHERE USER_ID = ? ORDER BY USER_ID DESC]
User user = new User();
user.setUserId(1L);
List<User> users1 = superDao.include("userId").queryList(user);

黑名单

跟白名单相反,黑名单内的字段将不被返回,当同时指定白名单和黑名单时,以白名单为准:

//[SELECT GMT_CREATE,GMT_MODIFY,USER_AGE,USER_ID FROM USER WHERE USER_ID = ? ORDER BY USER_ID DESC]
List<User> users = superDao.exclude("userName").where("userId", 1L).query(User.class);
//[SELECT GMT_CREATE,GMT_MODIFY,USER_ID FROM USER WHERE USER_ID = ? ORDER BY USER_ID DESC]
User user = new User();
user.setUserId(1L);
List<User> users1 = superDao.exclude("userName", "userAge").queryList(user);

排序

当不指定排序时,默认按id降序排列,像上面的情况就是默认排序,如果指定了具体排序字段和方式,则默认的将被替换,可以同时指定多个:

//[SELECT USER_NAME FROM USER WHERE USER_ID > ? ORDER BY  USER_ID ASC,GMT_CREATE ASC,USER_AGE DESC]
List<User> users = superDao.include("userName").asc("userId", "gmtCreate").desc("userAge").whereAssign("userId", ">", 1L).query(User.class);
//[SELECT GMT_CREATE,GMT_MODIFY,USER_AGE,USER_ID,USER_NAME FROM USER ORDER BY  USER_ID ASC,USER_AGE DESC]
User user = new User();
List<User> users1 = superDao.asc("userId").desc("userAge").queryList(user);

分页

分页功能被封装的十分简单,这可能是你用过的最方便的分页了,无须任何配置,它会自动分辨数据库,目前有MySql和Oracle两个实现,下面代码有详细的注释:

//指定执行分页,第1页,每页20条
PageControl.performPage(1, 20);
//数据库是mysql,实际执行的sql,同时会自动帮你查询出总记录数:
//SELECT GMT_CREATE,GMT_MODIFY,USER_AGE,USER_ID,USER_NAME FROM USER WHERE USER_ID > ? ORDER BY USER_ID DESC limit 0,20
//执行查询,跟平常的一样,
List<User> users = superDao.whereAssign("userId", ">", 1L).query(User.class);
//需要注意,执行分页后,这里返回的users将变为null,数据必须从PageControl中获取
//这是为了防止查询后直接拿查询的数据去使用,忘了清空分页信息,虽然理论上来说这并没有什么问题
//System.out.println(users == null);//输出true
//获取数据,强制数据必须从这里获取,是为了清空一些分页时用到的数据,如页码,每页大小等
//Pager pager = PageControl.getPager();
//获取查询的用户列表,如果参数传入VO对象,如UserVo.class将自动完成转换
//List<User> list = pager.getList(User.class);
//总记录数
//int itemsTotal = pager.getItemsTotal();

总的来说,完成分页只需要添加一行PageControl.performPage(1, 20);即可,查询操作跟平常不分页时并没什么区别,同时PageControl.performPage();方法是一个重载方法,可以传入实体对象(继承了Page类)或直接传入页码等:

//正常查询
List<User> users = superDao.whereAssign("userId", ">", 1L).query(User.class);
//分页查询
PageControl.performPage(1, 20);
superDao.whereAssign("userId", ">", 1L).query(User.class);
List<User> list = PageControl.getPager().getList(User.class);
User user = new User();
PageControl.performPage(user);
superDao.queryList(user);
Pager pager = PageControl.getPager();

有时候,你可能只想查询某一页的数据,并不需要总的记录数,这时候你可以指定最后一个参数为false,而减少一次count查询:

//分页查询
User user = new User();
//指定false,将不会进行总记录数的查询
PageControl.performPage(user,false);
superDao.queryList(user);
Pager pager = PageControl.getPager();

当然,分页方法也可以和其它查询方法一样,跟黑白名单、排序等功能组合使用:

//分页查询
User user = new User();
PageControl.performPage(user);
//[SELECT USER_NAME FROM USER ORDER BY  GMT_CREATE ASC,USER_AGE DESC limit 0,20]
superDao.include("userName").asc("gmtCreate").desc("userAge").queryList(user);
Pager pager = PageControl.getPager();

分页组件的分页查询sql是在运行时动态生成的,大大增加了方法的灵活性,且它绑定的对象是JdbcTemplate,而不是SuperDao,这就意味着不止是SuperDao,所有其它任何你自己实现的dao类都可以使用这个分页组件,

假设我有一个自己实现的BookDao:

/**
 * Created by liyd on 8/12/14.
 */
public class BookDaoImpl implements BookDao {
    public List<Book> queryBookList() {
        String sql = "select * from BOOK";
        return jdbcTemplate.query(sql, BeanPropertyRowMapper.newInstance(Book.class));
    }
}
在写代码时完全不需要考虑分页,这个方法将查询出表的所有记录。当你需要分页时不需要改动任何查询代码,同样只需添加一行PageControl.performPage()即可:
Book book = new Book();
//查询第二页,每页大小默认20条
book.setCurPage(2);
//指定分页
PageControl.performPage(book);
bookDao.queryBookList();

好了,差不多就介绍到这了,主要的功能也介绍完了,接下来就是讲讲如何实现了。

上一篇:
下一篇:
3 条评论
guarder · 1年前
支持下文

回复

song · 1年前
mysqlsuperdao求讲解一下

回复

zgpxiong · 1年前
还有实现吗?

回复