dao设计模式中的数据传输对象

Posted

技术标签:

【中文标题】dao设计模式中的数据传输对象【英文标题】:Data transfer object in dao design pattern 【发布时间】:2013-07-11 13:11:12 【问题描述】:

我对 DTO 应该包含哪些数据感到有些困惑。 例如,假设我们有两个表:User 和 Orders。 Orders 表包含 id_users,它是 user 表的外键。

显然,我有两个 DAO,mysqlUserDao 和 MysqlOrdersDao,具有 crud 操作,以及两个传输对象 User 和 Order,我在其中存储 jdbc 行集。

如果我想获取用户列表以及每个用户的所有订单,我应该怎么做:

1) 在我的MysqlUserDao中创建一个函数:getUsersAndOrders(select users.,orders. from users join orders) 我的用户 DTO 应该在我下订单的地方有一个 OrderList 属性?

2) 在我的 MysqlUserDao 中,我创建了一个函数 getAllUsers(select * from users), 而foreach用户我使用MysqlOrdersDao函数getOrder(id_user);

还有一些说明:

1) 我需要为数据库中的每个表创建一个 DAO 对象吗?还是只针对复杂的? 例如产品和图片,应该是 2 道还是只有 1 道?

2) DTO 对象应该只有属性和 setter getter,或者可以有其他方法,如 convertEuroToUsd 等。

谢谢

【问题讨论】:

【参考方案1】:

在您的场景中,#1 是最佳选择,因为 #2 会产生太多开销。

1) 在我的 MysqlUserDao 中创建一个函数:getUsersAndOrders(select users.,orders. from users join orders) 我的 User DTO 应该在我下订单的地方有一个 OrderList 属性?

说明: 1:如果你的数据库有很好的设计,那么为每个表做一个DAO是一个很好的方法。在某些情况下,您可以将 DAO 合并在一起(例如:继承)。

2:是的。它应该是一个普通的 bean(如果需要,也可以是 POJO)。我建议创建另一个层,您可以在其中定义您的工作流程。我似乎有人称这个额外的层为模型,有时是 DataManager,有时只是 Manager。

例如:创建订单时,您应该在订单表中插入一条记录,同时在通知表中插入一条记录(因为每次创建订单时最终用户都会收到电子邮件通知)

class OrderManager 
   private OrderDAO oDao;
   private NotificationDao nDao;

   public saveOrder(OrderDTO o) 
      Long orderId = oDao.save(o);
      NotificationDTO n = new NotificationDTO();
      n.setType(NotificationType.ORDER_CREATED);
      n.setEntityId(orderId);
      nDao.save(n);
   

更新: 在大多数情况下,我们可以这样说:

“经理”可以处理许多 DAO; DAO 不应包含其他 DAO 并与 DTO 绑定; DTO 可以包含其他 DTO

在处理集合时,LAZY 或 EAGER 加载有一个重要的想法。但这是另一个主题:D

【讨论】:

在您的示例中,我理解 OrderManager 的目的,但是如果我有一个简单的 DAO,只包含粗鲁操作,那么我认为 Manager 毫无意义。管理器中的插入函数如下所示: ` public insertOrder(OrderDto o ) oDao.insert(o)); ` .作为一项规则,传输对象应该包含所有其他处于连接关系的 DTO?像 orm 一样 @Catalin “作为一项规则,传输对象应该包含所有其他处于连接关系的 DTO?”。我想说这取决于,我们不能定义这么强的规则,有很多性能(如果你不加入,意味着你需要循环并稍后执行许多其他选择)和语义(用户是订单的内在组件吗? ) 需要考虑的问题。【参考方案2】:

免责声明: + 以下假设这些 DTO 主要用于持久性,即与 DAO 一起使用。 + 这种方法非常面向关系数据库持久性 + 假设一个用户可以下订单,但一个订单最多只能有一个用户 + 还有,你想分别查询/处理订单和用户

我会做以下事情:

用户的 DTO (UserDTO + UserDAO) 订单的 DTO(OrderDTO + OrderDAO) 连接两者的 DTO (UserOrderDTO + UserOrderDAO) 我不会在 UserDTO 中引用任何 OrderDTO 我可能在 OrderDTO 中有对 UserDTO 的引用,作为具有字符串 id 的属性(作为用户 id 的字符串 id),但我也可能没有。我假设是后者。 用于管理与订单 (OrderSA) 关联的不同 DAO 的服务应用程序

生成的代码如下:

class OrderManagerServiceApplication 
   private OrderDAO oDao;
   private UserDao uDao;
   private UserOrderDao uoDao;

   public saveOrder(OrderDTO o, String userId) 
      // Save the order
      Long orderId = oDao.save(o);
      // Save the association to the user who ordered
      UserOrderDTO uodto=new UserOrderDTO(orderId,userId);          
      uoDao.save(uodto);
   

   public List<OrderDTO> getOrdersForUser(String userId)  
      // get the orders associated to the user  
      List<String> orderIds=uoDao.getAllForUser(userId);
      // retrieve the order DTOs
      ArrayList<OrderDTO> result=new ArrayList<OrderDTO>();
      for (String orderId:orderIds)
        result.add(oDAO.getOrder(orderId));
      
      return result;
   


   public UserDTO getUserForOrder(Stirng orderId)  
      // get the user associated with the order
      String userId=uoao.getUserForOrder(orderId);
      // retrieve the user DTO
      return uDAO.getUser(userId);
   


【讨论】:

以上是关于dao设计模式中的数据传输对象的主要内容,如果未能解决你的问题,请参考以下文章

java中的dao模式

Java中的DAO模式啥是业务对象

Java网站开发中的DAO目录详细解释

在 Ruby 上设计 DAO

DAO 模式 - 它提供业务对象还是纯数据?

Java EE DAO / DTO(数据传输对象)设计模式