我一直在使用DAO模式来访问我正在构建的应用程序中的持久层。其中我实现的一件事情是为了验证,在我的DAO实现周围创建了一个“包装器”。该包装器将我的DAO实例作为构造函数参数进行接收,并实现与DAO类似的接口,唯一的例外是抛出异常的类型。
例如:
业务逻辑接口
public interface UserBLInt {
private void assignRightToUser(int userId, int rightId) throws SomeAppException;
}
DAO接口
public interface UserDAOInt {
private void assignRightToUser(int userId, int rightId) throws SomeJPAExcption;
}
业务逻辑实现
public class UserBLImpl implements UserBLInt {
private UserDAOInt userDAO;
public UserBLImpl(UserDAOInt userDAO){
this.userDAO = userDAO;
}
@Override
private void assignRightToUser(int userId, int rightId) throws SomeAppException{
if(!userExists(userId){
//throw an exception
}
try{
userDAO.assignRightToUser(userId, rightId);
} catch(SomeJpAException e){
throw new SomeAppException(some message);
}
}
}
DAO实现
public class UserDAOImpl implements UserDAOInt {
//......
@Override
public void assignRightToUser(int userId, int rightId){
em.getTransaction().begin();
User userToAssignRightTo = em.find(User.class, userId);
userToAssignRightTo.getRights().add(em.find(Right.class, rightId));
em.getTransaction().commit();
}
}
这只是一个快速的例子,但我的问题是,在 DAO 实现中似乎进行另一次检查以确保 User
不为 null 再添加 Right
是“冗余”的,但作为程序员,我看到了避免空指针异常的机会。
显然,在调用实体管理器的 find 方法后,我可以添加一个 null 检查并抛出异常,但这就是将 DAO 封装在业务逻辑实现中的全部目的,在此之前进行所有验证工作,以便 DAO 代码干净且不必做太多的 null 检查或逻辑处理。由于我在 DAO 周围有一个包装器,所以仍然在 DAO 中执行空值检查是一个好主意吗?我知道理论上对象可能会在业务逻辑调用和 DAO 调用之间被删除,这只是不太可能发生,检查 null 看起来像是重复的工作。类似这种情况的最佳实践是什么?
编辑:
这是否看起来像一个合适的 DAO 修改?
public EntityManager beginTransaction(){
EntityManager entityManager = entityManagerFactory.createEntityManager();
EntityTransaction entityTransaction = entityManager.getTransaction();
entityTransaction.begin();
return entityManager;
}
public void rollback(EntityManager entityManager){
entityManager.getTransaction().rollback();
entityManager.close();
}
public void commit(EntityManager entityManager){
entityManager.getTransaction().commit();
entityManager.close();
}
EntityManager
不是线程安全的,因此每个线程只能有一个。如果您为每个 DAO 都创建一个EntityManager
并且多个线程访问相同的 DAO 实例,则肯定会遇到(令人讨厌的)问题。这是我的建议:https://gist.github.com/acdcjunior/94363ea5cdbf4cae41c7 - acdcjuniorEntityManager
返回到业务层(类)。这是数据访问层泄漏的实现细节。 - acdcjunior