本文展示一套基於泛型與抽象類的 JavaEE 三層架構輕量封裝方案,涵蓋 DAO 層、Service 層與 Web 層調用,並整合 Spring + Hibernate 實作。透過介面與抽象類分離契約與實作,搭配泛型參數化實體類型與主鍵,大幅減少重複 CRUD 代碼,提升開發效率與維護性。
DAO層:GeneralDAO (介面) → AbstractGeneralDAOImpl (抽象基類) → AbstractSpringDAO (Spring+Hibernate實作) → 具體DAO介面/實作 Service層:GeneralService (介面) → AbstractServiceImpl (抽象基類) → 具體Service介面/實作 Web層:Action 直接注入 Service 介面調用業務邏輯
public interface GeneralDAO<T, ID extends Serializable> {
T findByID(ID id);
List<T> findAll();
PagingVO getPagingData(int currentPage, int pageSize);
T save(T entity);
void save(T... entity);
T update(T entity);
void update(Collection<T> entity);
void saveOrUpdate(T entity);
void saveOrUpdate(Collection<T> entities);
void delete(T entity);
void delete(ID id);
void delete(Collection<T> entities);
void merge(T entity); // 修正拼寫:marge → merge
void merge(T... entity);
int getCount();
}
public abstract class AbstractGeneralDAOImpl<T, ID extends Serializable> implements GeneralDAO<T, ID> {
protected final Class<T> persistenceClass;
protected final Class<ID> pkClass;
protected AbstractGeneralDAOImpl() {
// 透過反射解析泛型實際類型參數
this.persistenceClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
this.pkClass = (Class<ID>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[1];
}
}
public abstract class AbstractSpringDAO<T, ID extends Serializable> extends AbstractGeneralDAOImpl<T, ID> {
private HibernateTemplate hibernateTemplate;
// 標準 CRUD 委派給 HibernateTemplate
public List<T> findAll() { return getHibernateTemplate().loadAll(getPersistenceClass()); }
public T findByID(ID id) { return (T) getHibernateTemplate().get(getPersistenceClass(), id); }
public void delete(T entity) { getHibernateTemplate().delete(entity); }
public T save(T entity) { getHibernateTemplate().save(entity); return entity; }
public void saveOrUpdate(T entity) { getHibernateTemplate().saveOrUpdate(entity); }
public T update(T entity) { getHibernateTemplate().update(entity); return entity; }
public int getCount() {
return (Integer) getHibernateTemplate().execute(session -> {
Criteria c = session.createCriteria(getPersistenceClass());
c.setProjection(Projections.rowCount());
return c.uniqueResult();
});
}
// 其餘方法略...
}
public interface XtyhbDAO extends GeneralDAO<Xtyhb, Integer> {
Xtyhb findByNameAndPwd(String username, String password);
}
@SuppressWarnings("unchecked")
public class XtyhbDAOImpl extends AbstractSpringDAO<Xtyhb, Integer> implements XtyhbDAO {
public Xtyhb findByNameAndPwd(String username, String password) { /* HQL/CRITERIA 實作 */ return null; }
public PagingVO getPagingData(int currentPage, int pageSize) { /* 分頁實作 */ return null; }
}
public interface GeneralService<T, ID extends Serializable, DAO extends GeneralDAO<T, ID>> {
T findByID(ID id); List<T> findAll();
T save(T entity); void save(T... entity);
T update(T entity); void update(Collection<T> entity);
void saveOrUpdate(T entity); void saveOrUpdate(Collection<T> entities);
void delete(T entity); void delete(Collection<T> entities); void delete(ID id);
void merge(T entity); void merge(T... entity);
}
public abstract class AbstractServiceImpl<T, ID extends Serializable, DAO extends GeneralDAO<T, ID>> implements GeneralService<T, ID, DAO> {
private DAO dao;
// 所有方法委派給 DAO,並記錄日誌
public List<T> findAll() { log.info("findAll execute success"); return getDao().findAll(); }
public T findByID(ID id) { log.info("findById execute success"); return getDao().findByID(id); }
// 其餘委派方法略...
public DAO getDao() { return dao; }
public void setDao(DAO dao) { this.dao = dao; }
}
public interface XtyhbService extends GeneralService<Xtyhb, Integer, XtyhbDAO> {
Xtyhb findByNameAndPwd(Xtyhb xtyhb);
}
public class XtyhbServiceImpl extends AbstractServiceImpl<Xtyhb, Integer, XtyhbDAO> implements XtyhbService {
public Xtyhb findByNameAndPwd(Xtyhb xtyhb) {
return getDao().findByNameAndPwd(xtyhb.getYhmc(), xtyhb.getMm());
}
}
public class LoginAction {
private XtyhbService xtyhbService; // Spring 注入
public String login() {
xtyhb.setMm(MD5Encrypt.getMD5(xtyhb.getMm()));
Xtyhb loginUser = xtyhbService.findByNameAndPwd(xtyhb);
if (loginUser == null) { message = "無此用戶"; return FAILURE; }
if (XtyhbStateConst.DISABLE == loginUser.getYhzt()) { message = "用戶被禁用"; return FAILURE; }
// 權限選單構建邏輯...
ActionContextUtil.setAttr2Session("user", loginUser);
return Action.SUCCESS;
}
}
AbstractSpringDAO 注入 HibernateTemplate,符合 Spring 管理模式。此封裝模式適合中小型專案快速建立標準化分層架構,大型系統可在此基礎上引入 Repository 模式、規格模式等進階演進。