本文介绍怎么样使用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特性的情况要复杂多了。
分享到:
相关推荐
Java泛型与集合是Java编程中的核心概念,它们在实际开发中扮演着至关重要的角色。本书"Java Generics and Collections"深入探讨了这两个主题,帮助开发者编写更安全、更高效且可维护的代码。 首先,让我们来理解...
Java泛型(Generics)是Java SE 5.0引入的一种新特性,它允许程序员在编译时检查类型安全,并且所有的强制转换都是自动和隐式的,提高了代码的重用率。下面将根据给定的文件信息,深入解析Java泛型的一些核心知识点...
Java泛型和集合是Java编程语言中的核心特性,它们极大地提高了代码的类型安全性和可读性,同时也简化了集合操作。本资料 "[Java泛型和集合].(Java.Generics.and.Collections).Maurice.Naftalin&Philip.Wadler....
《Java Generics and Collections》是Java开发者必备的参考资料,它深入探讨了Java编程中的泛型(Generics)和集合(Collections)这两个核心概念。在Java编程中,泛型和集合框架是提高代码效率、可读性和类型安全性...
DAO类处理所有数据库操作,使得业务逻辑层可以专注于处理核心业务,而不必关心底层的数据存取细节。而泛型DAO是DAO模式的一个进阶应用,它通过引入泛型来提高代码的复用性和可维护性。 泛型(Generics)是Java 5...
Java中的方法重载指的是在同一个类中可以有多个同名方法,只要它们的参数类型或参数个数不同即可。泛型方法也可以重载,但必须保证在调用时能够明确区分不同的重载方法。 泛型擦除 泛型信息只存在于Java代码编译...
3. 泛型类:泛型类是使用类型参数定义的类,例如 LinkedList。 泛型的使用: 1. 定义泛型接口:使用类型参数定义接口,例如 public interface List。 2. 定义泛型类:使用类型参数定义类,例如 public class ...
本例子说明演示了Java范型使用的动机、范型类的使用、范型方法的使用,以及范型的缺陷:类型擦除(type erasure).因为,现在Java的反射机制不能确定集合中的对象类型! 在实际应用中,如果能够灵活应用范型和反射...
3. **实践编程中的Java泛型**:这一部分关注在实际开发中使用Java泛型时可能遇到的问题,比如如何设计泛型API、是否应该使类泛型化、混合使用泛型与非泛型Java时会发生什么情况等。 4. **编译器背后的Java泛型技术...
《Java开发手册1.6》是Java编程领域的权威参考资料,主要涵盖了Java Standard Edition 6(JSE 6)的API规范。此手册是Java开发者的重要工具,它详细阐述了Java 1.6版本中的各种类库、接口和方法,帮助程序员理解和...
类字面量(class literals)可以在运行时作为类型令牌使用,这对于反射操作或需要在运行时确定类型的情况下非常有用。 #### 通配符的更多应用 通配符不仅可以表示未知类型,还可以通过限定通配符(bounded ...