DAO 层应该实现哪些方法?

Posted

技术标签:

【中文标题】DAO 层应该实现哪些方法?【英文标题】:What methods the DAO layer should implement? 【发布时间】:2016-02-15 03:43:47 【问题描述】:

我现在正在编写 Web 应用程序,但在设计 DAO 层的阶段卡住了。已经浏览了有关该主题的各种文章,但仍未达到清晰的程度。 我的问题是: 在 DAO 类中允许声明和实现什么样的方法? 它们只是有限的 CRUD 操作集(创建、读取、更新、删除)吗?在开发业务逻辑层时使用一些适合您的具体需求的自定义方法扩展此集合是否被认为是一种好习惯? 例如: 我有一个名为 User 的实体类,其字段完全反映了相应的数据库表。假设我要在授权时验证用户的登录名和密码。在这种情况下,哪种方法更合适?我是否应该调用通用 CRUD 方法List<User> findAll() 来检索所有用户并在业务逻辑方法中验证这些具体的登录名和密码(类似于boolean validateUser(String login, String password, List<User> users))。或者我应该直接在 DAO 类中添加一些像 boolean checkUser(String login, String password) 这样的非 CRUD 方法?

【问题讨论】:

【参考方案1】:

我现在正在编写 Web 应用程序,但在设计 DAO 层的阶段卡住了。

您是使用普通的旧 servlet 手动编写它还是使用 Web 框架(例如 Spring MVC)来减轻您的痛苦?

    我的问题是:在 DAO 类中允许声明和实现什么样的方法?它们只是有限的 CRUD 操作集(创建、读取、更新、删除)吗?**

一般来说,是的——这些方法应该仅限于 CRUD 操作。

    使用适合您在开发业务逻辑层的具体需求的一些自定义方法扩展此集合是否被认为是一种好习惯?**

在合理范围内,是的。

例如:我有一个名为 User 的实体类,其中的字段完全反映了相应的数据库表。假设我要在授权时验证用户的登录名和密码。在这种情况下,哪种方法更合适?我是否应该调用通用 CRUD 方法 List findAll() 来检索所有用户并在业务逻辑方法中验证这些具体的登录名和密码(类似于 boolean validateUser(String login, String password, List users))。还是应该直接在 DAO 类中添加一些非 CRUD 方法,例如 boolean checkUser(String login, String password)?

除了您的 DAO 类应具有的标准 CRUD 方法之外,您还可以添加一个辅助方法,例如: User findUser(String login) 的工作是为指定的 login 参数返回填充的 User 对象,如果登录不存在,则返回 null。

User findUser(String login) 应该利用 List<User> findAll(),它应该已经存在于 DAO 类中的其余 CRUD 方法中。可以这样实现:

public User findUser(String login) 
    User user = null;
    final SearchCriteria criteria = buildSearchCriteria(login); // construct a search criteria from the login parameter
    List<User> users = findAll(criteria);  
    if (null != users) 
       assert (users.size() == 1) : "More than one user was matched - login must be unique.";
       user = users.get(0);
    
    return user;

总结一下,实现授权逻辑只需要2个方法:

    User findUser(String login) 在您的 DAO 层中,并且;

    boolean checkUser(String login, String password) 将在您的前端层中。如果您没有使用任何 Web 框架,则此方法将在您的 servlet 中实现,否则此方法将进入您的控制器类(如果您使用的是 MVC 框架)。

【讨论】:

感谢您如此详细的回复。是的,我在这里使用普通的 servlet(这只是培训项目,禁止使用框架)。因此,据我所知,为 dao 提供适用于特定实体的其他方法是完全可以的,如果我想修改一些信息,我也可以声明 updateLogin(String newLogin) 和 updateAddress(String newAddress) ,对吗? updateLogin(...), updateAddress(...) 等单独的方法过于精细,并且有悖于使用旨在帮助减少乏味的 DAO 类的目的。相反,您应该有一个通用的updateEntity(Entity entity) 用于更新,similar methods 用于实体级别 的创建、读取和删除操作。【参考方案2】:

简短的回答是否定的:不要在 dao 层添加任何业务逻辑。让每一层都有自己的责任,这样当其他人(甚至你)需要改变时,他们就会知道去哪里找。

编辑: 其他答案:

Q:DAO类中允许声明和实现哪些方法?

A:允许您访问数据库对象或其属性的方法。即 public User getOldUsers(), public boolean isUserExist(Long userId)etc...

问:它们只是有限的 CRUD 操作集(创建、读取、更新、删除)吗?

A:是的,您还可以控制持久性或事务属性

问:通用 CRUDS?

A:我从事的几乎所有项目都使用通用 CRUDS(AbstractDao 类)并添加其他方法

【讨论】:

感谢您的快速回复,但不能说我完全理解您。我想我错过了一些重要的概念。你说“不要在 dao 层添加任何业务逻辑”。但是,您刚刚列出的这些方法(例如boolean isUserExist(Long userId))不是业务逻辑的一部分。为什么我可以添加一些类似的方法boolean isUserExist(String login, String password) 并直接在DAO类中通过授权过程验证用户(参考我的示例)? 是的 isUserExist 不是最好的例子,你的通用 crud 可以有一个 isEntityExist 等方法......在业务逻辑中,你可以决定抛出异常或响应用户一些消息,记录可疑活动等...当您将所有这些带入 dao 时,dao 将成为应用程序,并且没有必要再添加一层 我说对了吗?你的意思是每个 dao 都应该包含相同的方法集。如果我有两个实体订单和用户,我可以创建 userDAO 方法来从数据库中检索一些特定于该实体值的方法,例如 String getUserLogin(int id) 方法的数量可以完全不同或相等,取决于您的选择。但是您将对大多数常用方法使用抽象。这里有几个抽象的 dao 示例:google.de/… 是的,正如你提到的,用户特定的方法会交给用户 dao

以上是关于DAO 层应该实现哪些方法?的主要内容,如果未能解决你的问题,请参考以下文章

java项目中都有哪些层?我知道有dao、service、util,还有啥?作用都是啥?

DAO 层实现

dao 层实现 的方法

mybatis怎么知道dao层调用了实体.xml里面哪个方法

SSH框架中POJO层, Dao层,Service层, Action层的功能理解

9-4DAO首页大接口Dao层实现和调用-1