最近因为事情比较多好久没写博客,一晃居然都几个月了。
之前随手写的Spring JdbcTemplate实现通用的泛型dao 和spring整合quartz整合动态定时任务系列,没想到会有那么多人向我要源码和demo, 这里要说声抱歉了,因为之前写的时候并没有特地的整理及示范的demo,也因为博客一直没更新,差不多导致这两个文章都烂尾了,趁这段时间把它们完成吧。
先说说Spring JdbcTemplate实现通用的泛型dao吧。
其实最初的目的是因为我个人要开发网站,为了方便。
hibernate不怎么喜欢用,早先用的mybatis感觉总是要写sql的xml比较麻烦,想着能不能用一个轻量的类似db-utils的东西(不得不说多少有些受osc的影响), 刚好spring jdbc是个类似的实现,所以就简单封装了下,没想到发出来之后关注的人挺多,看来这方面还是有实际需求的。
看过我之前博客的人应该知道,前面我应该算是有两个版本的实现了,现在要说的,应该算是第三个版本。下面说说它们的区别。
第一个版本:
叫它一般的实现版本吧,每个实体类都需要对应一个dao,这个dao也算是通用实现的dao吧,继承于超类的泛型实现,典型的代码如下:
public class UserDaoImpl extends BaseDaoImpl
implements UserDao {
}
缺点在于很多业务不强的实体在建立这个dao后,可能里面都没有实现内容,比较麻烦浪费。
另外对于in、!=或or等查询无能为力。
第二个版本:
第二个版本称作SuperDao吧,之前也有文章写过,下面是它的典型的查询代码:
List
users = superDao.include("userId")
.where("userName", "in", new Object[] { "liyd", "selfly" })
.and("userId", ">=", new Object[] { 17L }).or("userId", "<=", new Object[] { 1L })
.asc("userId").queryList(User.class);
黑名单、白名单、条件、排序等都是用dao来完成的,在业务职责划分上不怎么清晰,另外使用了ThreadLocal,并不是很好。
第三个版本:
也就是当前的版本,是听了群里一个朋友的建议,使用了类似Criteria的方式。将在后面做具体介绍。
之所以不停的修改,主要原因还是在使用的过程中碰到了太多不方便的地方,只有切实使用过才知道。
在这修改的过程当中,主要是围绕以下几个情况进行改进的,和上次SuperDao时是一致的:
1、查询时,需要某个字段不等于(column != value)某个值的时候。
2、查询时,需要某个字段等于多个值(column = value1 or column = value2)的时候。
3、需要以某个或多个字段特定排序的时候。
4、当表中有个字段比较大(clob等大字段及text等),查询时又不需要用到不想返回,节省性能时。
5、分页查询很不方便,当有以某个字段排序等要求时无法实现通用。
6、有时只需要更新某一个字段时,也需要new整个对象。
7、虽然通用,但是每个实体都需要建立一个号称通用的泛型dao,有些简单的dao里面就是空的,感觉很多余。
感受中最主要的就是这几个,其它就不列举了。如果你用过或封装过一些常规的通用dao,相信也会有这些感受。
目前的版本已经大致完成且使用了一段时间,感觉还算可以,总的来说有了以下改进:
1、解决了上面列出的所有问题,并且代码量反而更少更简洁了。
2、增加查询字段的黑白名单功能,要查哪些字段由你说了算。
3、单个字段的更新或查询可以直接set、where,不必再new整个对象,并且支持一个字段匹配多个值。
4、排序功能增强,多字段、升序降序自由组合。
5、方便强大的分页功能,无须额外操作,二三行代码搞定分页,自动判断数据库,无须指定。
6、不必再每个实体类对应建立一个继承于通用dao的dao了,一个dao自动判断操作所有表。
当然,这个dao封装的都是数据库通用的操作,对于某些数据库特有的操作来说,还需要自己去实现。
它的结构应该如下图:
![class][]
特有的操作由对应的子类去实现。
目前我用的比较多的数据库是Mysql,在使用过程中并没有碰到特有的需要封装的操作(分页在其它地方完成,下面会介绍),所以下面的介绍都是以JdbcDao类为主。
首先当然是来看一下dao的接口定义了,上代码:
public interface JdbcDao {
public Long insert(Object entity);
public Long insert(Criteria criteria);
public void save(Object entity);
public void save(Criteria criteria);
public void update(Criteria criteria);
public void update(Object entity);
public void delete(Criteria criteria);
public void delete(Object entity);
public void delete(Class clazz, Long id);
public void deleteAll(Class clazz);
public List queryList(Criteria criteria);
public List queryList(T entity);
public List queryList(T entity, Criteria criteria);
public int queryCount(Object entity);
public int queryCount(Criteria criteria);
public int queryCount(Object entity, Criteria criteria);
public T get(Class clazz, Long id);
public T get(Criteria criteria, Long id);
public T querySingleResult(T entity);
public T querySingleResult(Criteria criteria);
}
方法就是一般的增删改查操作,可以看到每个方法都有entity和criteria的重载,在使用时可以根据实际情况任选其一。
这里先来几个简单的使用示例,还是直接贴上我的测试类吧,比较全相信一看就能明白:
/**
* Created by liyd on 3/3/15.
*/
public class JdbcDaoTest extends BaseTest {
@Autowired
private JdbcDao jdbcDao;
private User user;
@Before
public void before() {
user = new User();
user.setUserName("liyd");
user.setUserAge(20);
user.setGmtCreate(new Date());
}
@Test
public void insert() {
Long id = jdbcDao.insert(user);
System.out.println(id);
}
@Test
public void insert2() {
Criteria criteria = Criteria.create(User.class).set("userName", "liyd22")
.set("userAge", 22).set("gmtCreate", new Date());
Long id = jdbcDao.insert(criteria);
System.out.println(id);
}
@Test
public void save() {
user.setUserId(-123L);
jdbcDao.save(user);
}
@Test
public void save2() {
Criteria criteria = Criteria.create(User.class).set("userId", -122L)
.set("userName", "liyd22").set("userAge", 22).set("gmtCreate", new Date())
.set("gmtModify", new Date());
jdbcDao.save(criteria);
}
@Test
public void update() {
user.setUserId(34L);
user.setUserName("liyd34");
user.setGmtCreate(null);
user.setGmtModify(new Date());
jdbcDao.update(user);
}
@Test
public void update2() {
Criteria criteria = Criteria.create(User.class).set("userName", "liydCriteria")
.set("userAge", "18").where("userId", new Object[] { 34L, 33L, 32L });
jdbcDao.update(criteria);
}
@Test
public void delete() {
User u = new User();
u.setUserName("selfly");
u.setUserAge(16);
jdbcDao.delete(u);
}
@Test
public void delete2() {
Criteria criteria = Criteria.create(User.class).where("userName", new Object[] { "liyd2" })
.or("userAge", new Object[] { 64 });
jdbcDao.delete(criteria);
}
@Test
public void delete3() {
jdbcDao.delete(User.class, 25L);
}
@Test
public void queryList() {
User u = new User();
u.setUserName("liyd");
List<User> users = jdbcDao.queryList(u);
for (User us : users) {
System.out.println(us.getUserName() + " " + us.getUserAge());
}
}
@Test
public void queryList1() {
List<User> users = jdbcDao.queryList(Criteria.create(User.class));
for (User us : users) {
System.out.println(us.getUserName() + " " + us.getUserAge());
}
}
@Test
public void queryList2() {
PageControl.performPage(1, 2);
Criteria criteria = Criteria.create(User.class).include("userName", "userId")
.where("userName", new Object[] { "liyd" }).asc("userId");
jdbcDao.queryList(criteria);
List<User> users = PageControl.getPager().getList(User.class);
for (User us : users) {
System.out.println(us.getUserId() + " " + us.getUserName() + " " + us.getUserAge());
}
}
@Test
public void queryList3() {
Criteria criteria = Criteria.create(User.class).exclude("userId")
.where("userName", new Object[] { "liyd" }).asc("userId").desc("userAge");
List<User> users = jdbcDao.queryList(criteria);
for (User us : users) {
System.out.println(us.getUserId() + " " + us.getUserName() + " " + us.getUserAge());
}
}
@Test
public void queryList4() {
Criteria criteria = Criteria.create(User.class).where("userName", "like",
new Object[]{"%liyd%"});
User user1 = new User();
user1.setUserAge(16);
List<User> users = jdbcDao.queryList(user1, criteria.include("userId"));
for (User us : users) {
System.out.println(us.getUserId() + " " + us.getUserName() + " " + us.getUserAge());
}
}
@Test
public void queryList5() {
List<User> users = jdbcDao.queryList(Criteria.create(User.class));
for (User us : users) {
System.out.println(us.getUserId() + " " + us.getUserName() + " " + us.getUserAge());
}
}
@Test
public void queryCount() {
User u = new User();
u.setUserName("liyd");
int count = jdbcDao.queryCount(u);
System.out.println(count);
}
@Test
public void queryCount2() {
Criteria criteria = Criteria.create(User.class).where("userName", new Object[]{"liyd"})
.or("userAge", new Object[]{27});
int count = jdbcDao.queryCount(criteria);
System.out.println(count);
}
@Test
public void get() {
User u = jdbcDao.get(User.class, 23L);
System.out.println(u.getUserId() + " " + u.getUserName() + " " + u.getUserAge());
}
@Test
public void get2() {
Criteria criteria = Criteria.create(User.class).include("userName");
User u = jdbcDao.get(criteria, 23L);
System.out.println(u.getUserId() + " " + u.getUserName() + " " + u.getUserAge());
}
@Test
public void querySingleResult() {
User u = new User();
u.setUserName("liyd");
u.setUserAge(16);
u.setUserId(23L);
u = jdbcDao.querySingleResult(u);
System.out.println(u.getUserId() + " " + u.getUserName() + " " + u.getUserAge());
}
@Test
public void querySingleResult2() {
Criteria criteria = Criteria.create(User.class).where("userName", new Object[] { "liyd" })
.and("userId", new Object[]{23L});
User u = jdbcDao.querySingleResult(criteria);
System.out.println(u.getUserId() + " " + u.getUserName() + " " + u.getUserAge());
}
}
下一章将讲解实现的过程,待续。。。
[class]: