本文介紹怎么樣使用Java Generics來簡化數(shù)據(jù)庫存取類DAO的開發(fā),并給出了一個完整的例子,大家可以把代碼用在實際的開發(fā)應(yīng)用中。
在系統(tǒng)開發(fā)中,為了降低耦合性,一般把跟數(shù)據(jù)庫有關(guān)的操作封裝在被叫做DAO(Dao Access Object)的類里。一般DAO的封裝有以下幾個原則:
1、一個表操作封裝成一個DAO。例如:操作表User的DAO封裝為UserDao.java,操作UserRole的DAO封裝為UserRole.java等
2、具有良好的接口定義。為了使用簡單以及不至于被錯誤調(diào)用,DAO接口必須有具體的型定義。例如:可以直接
User user = userDao.get(userId);取得指定userId的User,而不必進行強制類型轉(zhuǎn)換 User user = (User)userDao.get(userId); [X]
為了避免誤操作,userDao.delete(UserRole);應(yīng)該在編譯期就報錯。
為了對DAO進行良好的封裝,JDK1.5之前,DAO開發(fā)是一個大量重復代碼的體力過程;JDK1.5開始引入了Generics概念,我們可以利用JDK1.5的Generics特性大大簡化DAO開發(fā)。
Generics概念
Java的Generics就是Java的泛型,類似于C++的模板概念,Generics介紹起來比較復雜,簡單說來,泛型從語言特性的底層上支持,可以讓你為某些相似功能定義一個具有統(tǒng)一接口的通用模板,該模板可以接收任意類型并應(yīng)用到類成員變量的類型,方法的參數(shù)類型,方法的返回值類型等;并可以在編譯期支持類型的安全轉(zhuǎn)換。舉例說:
java.util.List是一個泛型,一個定義為List<User> userList;的變量userList,可以通過User user = userList.get(0);便可直接得到User,不用經(jīng)過類型的強制轉(zhuǎn)換了。
Generics更詳細的介紹請參考相關(guān)文章,這里不做詳述。
下面舉例我們給出2種DAO的封裝方法,一種是不使用Java Generics特性的一般封裝方法;一種是使用泛型的封裝方法。通過比較,我們會發(fā)現(xiàn)Java的Generics特性到底為我們簡化了哪些工作。
使用Java Generics特性封裝DAO
文件名 | 說明 |
---|---|
IDao.java | dao的頂層抽象接口 |
AbstractDao.java | IDao的實現(xiàn)類,實現(xiàn)了get/update/delete等基本操作 |
User.java | USER表對應(yīng)的entity定義 |
IUserDao.java | USER表操作DAO接口定義 |
UserDao.java | USER表操作DAO實現(xiàn) |
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的封裝。該封裝也是一個具有良好結(jié)構(gòu)性的封裝。
文件列表2:
文件名 | 說明 |
---|---|
DaoUtils.java | dao通用工具類,提供get/update/delete等基本操作 |
User.java | USER表對應(yīng)的entity定義 |
IUserDao.java | USER表操作DAO接口定義 |
UserDao.java | USER表操作DAO實現(xiàn) |
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的實現(xiàn)比使用Java Generics特性的情況要復雜多了。