拥有单个类实现整个应用程序中的每个DAO接口会是一个相当糟糕的设计。
更典型的模式是拥有一个BaseDAO接口(也经常称为GenericDAO),并且拥有JPABaseDAO、JDBCBaseDAO等。这些基类将包含诸如find/get/read、save/store/persist、update/modify和delete/remove/purge之类的方法。
像UserDAO这样的特定DAO接口然后继承自BaseDAO,而像JPAUserDAO这样的具体实现则从JPABaseDAO扩展。
一个BaseDAO接口可能看起来像这样:
public interface BaseDAO <T> {
T getByID(Long ID);
T save(T type);
T update(T type);
void delete(T type);
}
一个 UserDAO
接口:
public interface UserDAO extends BaseDAO<User> {
List<User> getAllAuthorized();
}
一个实现该接口的JPABaseDAO
的简单示例:
@Stateless
public class JPABaseDAO<T> implements BaseDAO<T> {
@PersistenceContext
private EntityManager entityManager;
private final Class<T> entityType;
@SuppressWarnings("unchecked")
public JPABaseDAO() {
this.entityType = ((Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]);
}
@Override
public T getByID(Long ID) {
return entityManager.find(entityType, ID);
}
@Override
public T save(T type) {
return entityManager.persist(type);
}
@Override
public T update(T type) {
return entityManager.merge(type);
}
@Override
public void delete(T type) {
entityManager.remove(entityManager.contains(type) ? type : entityManager.merge(type));
}
}
以下是一些继承自UserDAO
的示例实现:
@Stateless
public class JPAUserDAO extends JPABaseDAO<User> implements UserDAO {
@PersistenceContext
private EntityManager entityManager;
@Override
public List<User> getAllAuthorized() {
return entityManager.createNamedQuery("User.getAllAuthorized", User.class)
.getResultList();
}
}
实际上,基类通常可以透明地执行一些其他操作,例如检查实体是否实现了某种可审计接口,并自动设置修改日期和用户等。
使用EJB实现DAO时,更改实现的一种策略是将所有JDBC实现放在一个包中,将所有JPA实现放在另一个包中。然后只在您的构建中包含一个实现包。