DAO每个实体或每个用例

时间:2014-12-14 23:54:02

标签: java design-patterns dao

我有一种情况,我想我应该为每个实体或每个用例创建一个DAO。

我有一个表“user”,用于存储用户的登录信息。

create table user (user_id varchar(50) not null primary key, password varchar(50))

我有一个表“user_login_history”,它存储用户在系统中登录的次数的历史记录。

create table user_login_history (user_login_history_id int not null identity(1,1) primary key, user_id varchar(50) not null foreign key references user(user_id), login_date datetime not null)

这是用例:对于用户登录系统,他/她应该通过这两项检查:

  1. 用户ID和密码应在用户表中匹配
  2. 用户最后一次登录系统后30天没有通过。
  3. 所以我有一个实体用户

    public class User {
        private String userId;
        private String password;
        public String getUserId() { return this.userId; }
        public void setUserId(String userId) { this.userId = userId; }
        public String getPassword() { return this.password; }
        public void setPassword(String password) { this.password = password; }
    } 
    

    我有一个实体 UserLoginHistory

    public class UserLoginHistory {
        private int userLoginHistoryId;
        private User user;
        private java.util.Date loginDate;
        public int getUserLoginHistoryId() { return this.userLoginHistoryId; }
        public void setUserLoginHistoryId(int userLoginHistoryId) { this.userLoginHistoryId = userLoginHistoryId; }
        public User getUser() { return this.user; }
        public void setUser(User user) { this.user = user; }
        public java.util.Date getLoginDate() { return this.loginDate; }
        public void setLoginDate(java.util.Date loginDate) { this.loginDate = loginDate; }
    }
    


    所以我认为我有两个选择:

    1)按实体创建DAO,即2个DAO:

        用户实体的 UserDAO ,该实体将基于“用户”表格和

         UserLoginHistory 实体的 UserLoginHistoryDAO ,该实体将基于“user_login_history”表格

    public interface UserDAO {
        public User getUser(String userId, String password);
    }
    
    public interface UserLoginHistoryDAO {
        public UserLoginHistory getLastUserLoginHistory(String userId);
    }
    

    2)通过用例创建DAO,这意味着1 DAO:

         LoginDAO ,它将包含此用例所需的所有sql。

    public interface LoginDAO {
        public User getUser(String userId, String password);
        public UserLoginHistory getLastUserLoginHistory(String userId);
    }
    

    哪种选择更好?为什么?

    如果我选择1,如果我需要使用“user”和“user_login_history”表的查询并返回两个表中的列,该怎么办?在那种情况下DAO这些类型的查询会去哪? UserDAO或UserLoginHistoryDAO或复合的新DAO?

    由于

3 个答案:

答案 0 :(得分:1)

我建议有第三个选项,你可以保留这两个DAO(在访问器和db表之间有一对一的映射),然后覆盖第三个访问器,这有助于更容易地操作更低级别的API。第三个访问器需要另外两个访问器来构造,所以;

public LoginAccess(final UserDAO userAccess, 
                   final UserLoginHistoryDAO userHistoryAccess)

这种方法的好处是;

  1. 您可以尽可能降低访问者的范围 - 如果预期用途仅通过public,则用户/用户历史记录DAO实施是否需要LoginAccess个访问者?
  2. 您可以为此设置创建更多类似单元的测试用例。所有数据库级别的测试都更多地放在集成测试的一面,不过每个基于表的查询的一组测试都是好的,每个函数的一组测试(不用担心使用的SQL)也很好。相反,在一个步骤中检查函数和SQL的一组测试本质上更脆弱。
  3. 第三种方法更紧密地遵循SOLID原则
  4. 我认为1& 2是关键 - 通常我发现如果有一种方法可以编写更有效的单元测试并减少面向公众的API,那么我将采用这种方法。如果后来我的方法被证明是不合适的(可能!)我有一个强大的测试套件,我可以积极地重构。

答案 1 :(得分:1)

我认为正确的方法是使用每个实体/表的DAO,然后使用另一个上层(服务/业务等)来使用这些DAO来实现所需的功能。这种方法更具可扩展性,可以保持代码清洁。

在这种情况下,您可以使用LoginService调用UserDAO和UserLoginHistortDAO来实现所需的功能。

我认为上述方法的唯一例外是性能,其中我们优先考虑性能而不是其他非功能性要求。在这种情况下,我们可能必须根据用例而不是实体/表来设计我们的DAO。

答案 2 :(得分:0)

始终将DAO创建为数据库镜像,每个数据库对象一个。这将降低现在和未来应用层的复杂性