本文介绍怎么样使用Java Generics来简化数据库存取类DAO的开发,并给出了一个完整的例子,大家可以把代码用在实际的开发应用中。
在系统开发中,为了降低耦合性,一般把跟数据库有关的操作封装在被叫做DAO(Dao Access Object)的类里。一般DAO的封装有以下几个原则:
1、一个表操作封装成一个DAO。例如:操作表User的DAO封装为UserDao.java,操作UserRole的DAO封装为UserRole.java等
2、具有良好的接口定义。为了使用简单以及不至于被错误调用,DAO接口必须有具体的型定义。例如:可以直接
User user = userDao.get(userId);取得指定userId的User,而不必进行强制类型转换 User
user = (User)userDao.get(userId); [X]
为了避免误操作,userDao.delete(UserRole);应该在编译期就报错。
为了对DAO进行良好的封装,JDK1.5之前,DAO开发是一个大量重复代码的体力过程;JDK1.5开始引入了Generics概念,我们可以利用JDK1.5的Generics特性大大简化DAO开发。
Generics概念
Java的Generics就是Java的泛型,类似于C++的模板概念,Generics介绍起来比较复杂,简单说来,泛型从语言特性的底层上支持,可以让你为某些相似功能定义一个具有统一接口的通用模板,该模板可以接收任意类型并应用到类成员变量的类型,方法的参数类型,方法的返回值类型等;并可以在编译期支持类型的安全转换。举例说:
java.util.List是一个泛型,一个定义为List<User> userList;的变量userList,可以通过User
user = userList.get(0);便可直接得到User,不用经过类型的强制转换了。
Generics更详细的介绍请参考相关文章,这里不做详述。
下面举例我们给出2种DAO的封装方法,一种是不使用Java Generics特性的一般封装方法;一种是使用泛型的封装方法。通过比较,我们会发现Java的Generics特性到底为我们简化了哪些工作。
使用Java Generics特性封装DAO
文件名 |
说明 |
IDao.java |
dao的顶层抽象接口 |
AbstractDao.java |
IDao的实现类,实现了get/update/delete等基本操作 |
User.java |
USER表对应的entity定义 |
IUserDao.java |
USER表操作DAO接口定义 |
UserDao.java |
USER表操作DAO实现 |
HelloGenerics.java |
测试类 |
IDao.java
// super dao interface
public
interface IDao <T, PK
extends Serializable> { public
T get(PK pk); public
List <T>getAll(); public
PK save(T entity); public
void
update(T entity); public
void
saveOrUpdate(T entity); public
void
delete(T entity);
} |
AbstractDao.java
//super abstract dao class
public
abstract
class
AbstractDao <T, PK
extends Serializable>implements
IDao<T, PK> {
private
Class clz;
public
AbstractDao(Class clz) {
this.clz =
clz;
}
public
T get(PK pk) {
return
(T)getSession().get(clz, pk);
}
public
List <T>getAll() {
return
getSession().createCriteria(clz).list();
}
public
PK save(T entity) {
return
(PK)getSession().save(entity);
}
public
void
update(T entity) {
getSession().update(entity);
}
public
void
saveOrUpdate(T entity) {
getSession().saveOrUpdate(entity);
}
public
void
delete(T entity) {
getSession().delete(entity);
}
private
Session session;
protected
Session getSession() {
//wrap
session in a class such as HibernateUtils, then you can use HibernateUtils.getCurrentSession()
for getting a session.
return
session;
}
}
|
User.java
//persist entity
public
class
User { private
String id; private
String name; public
String getId() { return
id; } public
void
setId(String id) { this.id
= id; } public
String getName() { return
name; } public
void
setName(String name) { this.name
= name; }
//... setter/getter
HERE
} |
IUserDao.java
//User Dao interface
public
interface
IUserDao extends
IDao <User, String> { //
all are empty
} |
UserDao.java
//UserDao Implementation
public
class
UserDao extends
AbstractDao <User, String>
implements IUserDao { public
UserDao() { super(User.class);
} //
or use the following constructor
//public
UserDao(Class<User> type) {
// super(type);
//}
} |
HelloGenerics.java
public
class
HelloGenerics { public
static
void
main(String[] args) { IUserDao
userDao = new
UserDao(); User
user = userDao.get("1");
if
(user != null)
{ System.out.println(user.getName());
}
List<User>
userList = userDao.getAll(); for
(User u:userList) { System.out.println(user.getName());
} }
} |
我们可以看到IUserDao.java与UserDao.java非常简单。
不使用Java Generics特性DAO的封装
同样,我们给出不使用Java Generics特性DAO的封装。该封装也是一个具有良好结构性的封装。
文件列表2:
文件名 |
说明 |
DaoUtils.java |
dao通用工具类,提供get/update/delete等基本操作 |
User.java |
USER表对应的entity定义 |
IUserDao.java |
USER表操作DAO接口定义 |
UserDao.java |
USER表操作DAO实现 |
HelloGenerics.java |
测试类 |
DaoUtils.java
public
class
DaoUtils {
public
static
Object get(Class clz, Serializable pk) { return
getSession().get(clz, pk); }
public
static
List getAll(Class clz) { return
getSession().createCriteria(clz).list(); }
public
static
Serializable save(Object entity) { return
getSession().save(entity); }
public
static
void
update(Object entity) { getSession().update(entity);
} public
static
void
saveOrUpdate(Object entity) { getSession().saveOrUpdate(entity);
} public
static
void
delete(Object entity) { getSession().delete(entity);
} private
static
Session session; protected
static
Session getSession() { //wrap
session in a class such as HibernateUtils, then you can use HibernateUtils.getCurrentSession()
for getting a session.
return
session; }
} |
User.java
//persist entity
public
class
User { private
String id; private
String name; public
String getId() { return
id; } public
void
setId(String id) { this.id
= id; } public
String getName() { return
name; } public
void
setName(String name) { this.name
= name; }
//... setter/getter
HERE
} |
IUserDao.java
//User Dao interface
public
interface
IUserDao { public
User get(String pk); public
List getAll(); public
String save(User entity); public
void
update(User entity); public
void
saveOrUpdate(User entity); public
void
delete(User entity);
} |
UserDao.java
//UserDao Implementation
public
class
UserDao implements
IUserDao { public
User get(String pk) { return
(User)DaoUtils.get(User.class, pk); }
public
List getAll() { return
DaoUtils.getAll(User.class);
} public
String save(User entity) { return
(String)DaoUtils.save(entity); }
public
void
update(User entity) { DaoUtils.update(entity);
} public
void
saveOrUpdate(User entity) { DaoUtils.saveOrUpdate(entity);
} public
void
delete(User entity) { DaoUtils.delete(entity);
}
} |
HelloGenerics.java
public
class
HelloGenerics { public
static
void
main(String[] args) { IUserDao
userDao = new
UserDao(); User
user = userDao.get("1");
if
(user != null)
{ System.out.println(user.getName());
}
List<User>
userList = userDao.getAll(); for
(User u:userList) { System.out.println(user.getName());
} }
} |
我们注意到IUserDao.java与UserDao.java的实现比使用Java Generics特性的情况要复杂多了。
|