【问题标题】:How to design a DAO class? [closed]如何设计一个 DAO 类? [关闭]
【发布时间】:2013-11-07 19:22:35
【问题描述】:

设计 DAO 类的最佳方式应该是什么?

方法#1: 将 DAO 类设计为对象

class Customer {
//customer class
}

class CustomerDAO {
  public void saveCustomer(Customer customer) {
  //code
  }

  public Customer getCustomer(int id) {
  //code
  }
}

//Client code
class client {
  public static void main(String[] args) {

   CustomerDAO customerDAO = new CustomerDAO();
   Customer customer = new Customer();
   customerDAO.saveCustomer(customer);
  }
}

方法#2: 使用静态方法设计 DAO 类(又名静态类)

class Customer {
//customer class
}

class CustomerDAO {
  public static void saveCustomer(Customer customer) {
  //code
  }

  public static Customer getCustomer(int id) {
  //code
  }
}

//Client code
class client {
  public static void main(String[] args) {

   Customer customer = new Customer();
   CustomerDAO.saveCustomer(customer);
  }
}

在方法#1 中,我必须在所有客户端代码中创建一个 DAO 类的对象(其他选项是传递 DAO 的引用)。而在方法#2 中,我不必创建对象,并且可以设计静态方法而无需状态跟踪。

那么哪种方法是设计 DAO 类的最佳方法?

【问题讨论】:

  • 使用方法#1并使用像Spring这样的IOC容器注入对它的引用
  • 奇怪的是,没有人提到BalusC:DAO tutorial - the data layer 提供的这么好的和内容丰富的教程。阅读它,您将找到许多与 DAO 设计和实现相关的问题的答案。

标签: java


【解决方案1】:

我会推荐方法 #1,但会使用 Spring 进行依赖注入,而不是直接实例化 DAO。

这样,对于客户端代码的单元测试,您可以替换模拟 DAO,并验证是否使用适当的参数调用了正确的 DAO。 (Mockito 在这里很有用。)

如果你使用静态方法,那么单元测试就困难得多,因为静态方法不能被覆盖。

【讨论】:

  • +1 我懒得自己写这个答案。但它会和这个非常相似:-)
  • 如果来自 DAO 对象的客户(用户)之一代表当前登录的客户(用户)怎么办。你会提供像 getCurrentCustomer() 这样的方法,还是对 DAO 类是透明的,并且这个用户总是通过 id 获得?
  • @Piotr 我认为 DAO 不应该关心请求来自谁。
  • 那么你会在哪里存储登录用户的ID?你会把它从一个地方传递到另一个地方吗?你会把它存储在一些单例存储类中吗?也许你碰巧知道登录用户和/或用户 DAO 设计的任何好例子?
  • @Piotr 如果您添加更多上下文,这对 SO 来说可能是一个好问题。在一个 2.5 年前的问题上,这将比 cmets 提供更多的可见性。
【解决方案2】:

有更多的抽象:

interface IDAO<T> {

  public save(T t);
  public T getById(int id);
  //...etc

}

然后

public CustomerDao implements IDAO<Customer>{
   public save(Customer c){
        //Code here
    }
   public Customer getById(int id){
      //Code here
    }
}

和DAO到另一个域

public UniversityDao implements IDAO<University>{

     public save(University u){
       //Code here
      }
     public University getById(int id){
        //Code here
     }
}

现在表示层或主类将包含如下代码:

IDAO  dao;
dao=new CustomerDao();
//...
dao=new UniversityDao();

【讨论】:

    【解决方案3】:

    我也会选择选项 1,但我也建议您对接口进行编程。创建一个接口来设置 DAO 必须提供的功能,然后您可以根据需要使用不同的类来实现这些功能。

    public interface CustomerDao {
        public void saveCustomer(Customer customer);
    
        public Customer getCustomer(int id);
    }
    

    那么你就可以拥有class SimpleCustomerDao implements CustomerDAO {/*code here*/}

    在您的main(以及您需要的任何其他地方)中,您将拥有:

    //Note that you have an interface variable and a real class object 
    CustomerDao customerDao = new SimpleCustomerDao();
    

    你可以弄清楚这样做的好处!

    是的,如果您使用SpringGuice,那么请使用依赖注入!

    【讨论】:

      【解决方案4】:

      参考文章如何编写通用 DAO(使用 Spring AOP): Don't repeat the DAO!

      您可以找到适用于您的技术堆栈的通用 DAO 实现示例(只需 google“不要重复 DAO my_technology”)。

      【讨论】:

        【解决方案5】:

        我更喜欢分层方法,这种方法简单地告诉我们的是:

        1. 你有你的模型类 Customer
        2. 您正在通过接口 CustomerDAO 与客户签订合同

          public interface CustomerDAO{
          
              public void saveCustomer(Customer customer);
              public Customer getCustomer(int id);
          }
          
        3. 你有一个像 CustomerDAOImpl 这样的具体实现

          public class CustomerDAOImpl extends CustomerDAO{
          
              public void saveCustomer(Customer customer){
                saveCustomer(customer);
              }
          
              public Customer getCustomer(int id){
                return fetchCustomer(id);
              }
          }
          

        然后编写一个管理器来管理这些或封装一些其他 DAO,例如:

        public class ManagerImpl extends Manager{
            CustomerDAO customerDAOObj;
        
            // maybe you need to collect
            // all the customer related activities here in manger
            // because Client must not bother about those things.
        
            UserBillingDAO userBillingDAOObj; 
        
            public void saveCustomer(Customer customer){
              customerDAOObj.saveCustomer(customer);
            }
        
            public Customer getCustomer(int id){
              return customerDAOObj.fetchCustomer(id);
            }
        
            // Note this extra method which is defined in 
            //UserBillingDAO which I have not shown, but you are exposing 
            //this method to your Client or the Presentation layer.
        
             public boolean doBillingOFCustomer(id) {
                return userBillingDAOObj.doBilling(id);
            }
        }
        

        现在表示层或主类将包含如下代码:

        public static void main(String... ar){
             Manager manager = new ManagerImpl();
             manager.saveCustomer();
            // or manager.doBillingOfCustomer(); // etc
        }
        

        【讨论】:

        • ` public void saveCustomer(Customer customer){ saveCustomer(customer); }` LOL + 你有像public Customer getCustomer(int id); 这样的错误,然后是customerDAOObj.fetchCustomer。更不用说你的格式了......修复那些 - 直到那时
        猜你喜欢
        • 2018-06-24
        • 1970-01-01
        • 2014-12-31
        • 1970-01-01
        • 2021-07-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-09-16
        相关资源
        最近更新 更多