如何将查询中的记录放入DAO?

时间:2009-06-22 10:08:11

标签: coldfusion dao cfc gateway

我编写了一个网关来从我的数据库中获取结果集。如何将每一行存储在一个单独的dao中,以便我可以进一步操作每个记录?或者我可以直接访问结果集来获取记录吗?

这是我的网关(顺便说一下,我应该将cfquery中的条件逻辑编写成一个单独的cfc来扩展这个吗?)

<cfcomponent name="MaterialDao" hint="data access object" output="false">
 <cffunction name="init" hint="constructor" access="public" output="false" returntype="MaterialDao">
  <cfargument name="dsn" type="String" required="true" hint="datasource" />
  <cfset variables.instance.dsn = arguments.dsn />
  <cfreturn this />
 </cffunction>

 <cffunction name="readMaterial" hint="read" access="public" output="false" returntype="Query">
  <cfargument name="district" type="String" />
  <cfset var qReadMaterial = "" />
  <cfquery name="qReadMaterial" datasource="#variables.instance.dsn#">
   <cfif StructKeyExists(arguments,"district")>
   SELECT A.NR, A.BEZ, D.BES, D.STA
   <cfelse>
   SELECT A.NR, A.BEZ
   </cfif>
   FROM  DEK AS D INNER JOIN ART AS A
   ON D.NR = A.NR
   WHERE 0=0
   <cfif StructKeyExists(arguments,"district")>
    AND D.BEZ = #arguments.district#
   </cfif>
   ORDER BY A.BEZ
 </cfquery>
 <cfreturn qReadMaterial />
 </cffunction>
</cfcomponent>

我已经阅读了很多文章,似乎对这个问题有不同的看法(DAO vs. Gateway,DAO&amp; Gateway等)。什么是最佳实践,专业人士做什么?

3 个答案:

答案 0 :(得分:3)

专业人员只使用一种模式用于数据库访问层。 DAO和Gateway的使用是一个误称,我不确定它从哪里开始,但似乎只存在于ColdFusion人群中。 DAO和网关模式几乎可以提供相同的功能,但我认为在讨论数据库交互时,DAO更符合要求。

DAO应该包括CRUD方法的功能以及返回的记录集。由于CRUD和基本记录集具有高度重复性,因此我使用代码生成器为此交互创建代码,然后自定义我需要的内容。这是条件逻辑选择所需记录的好地方。

正如Aaron所提到的,由于创建对象的性能开销,在ColdFusion中为数据库中的一组记录返回一个对象数组是不可行的。我通常只在我的视图中使用从DAO返回的基本查询。但是,如果我正在建模的东西在视图中需要一些行为,那么我将使用类似于Peter Bell所做的事情将查询放在一个对象中。

答案 1 :(得分:2)

几个月前,彼得贝尔发布了迭代业务对象CFC,它有一个很棒的演示文稿,它允许你使用这个简单的框架一次获取多条记录并迭代一条记录:http://ibo.riaforge.org/。在CF生成对象之前要快一点,回收单个对象实例并重新填充属性可能是最好的。也许这可以帮助您一次将一条记录加载到DAO中。

条件逻辑可以进入网关或Manager CFC。通常情况下,我会包含简单的逻辑,就像您在CFC中直接发布的逻辑一样。

一些建议,您可能希望将参数设置为不需要,并使用if(structKeyExists(arguments,“distinct”)){做某事}进行简单检查。

此致

-Aaron Greenlee

答案 2 :(得分:1)

在我们公司,几个月来我们一直在思考这个问题,通过RDS尝试Adobe CF DAO创建者以及其他一些旧版本(任何人都记得CFPowerTools?)。

我们最终决定编写自己的DAO代码生成器,我想我会在这里分享我们的想法。我们决定的原因是因为我们需要为SQL添加锁定提示,我们希望使其更高效,更安全和更清洁。

我们决定的设置是创建一个预定义的基础DAO对象(称为DAO.cfc),它所有生成的“表”DAO都被扩展。它只是一些实用方法,但关键是我们可以添加任何其他功能,我们需要所有生成的DAO才能访问。

因此,我们通过从数据库中选择一个表(使用CF管理API)自动生成代码,并使用常用的init,setter和getter创建[TableName].cfc DAO,这样就是基本的CRUD内容。

除此之外,我们还会生成[TableName]GatewayBase.cfc[TableName]Gateway.cfc[TableName]Gateway.cfc延伸[TableName]GatewayBase.cfc

因此,对于在名为“Customers”的表上运行的示例DAO,创建的文件为:

Customers.cfc /* extends DAO.cfc [not created, already exists] */
CustomersGateway.cfc 
CustomersGatewayBase.cfc /* extends CustomersGateway */

因此,我们的想法是网关提供了一种处理许多“客户”记录的方法 - 在处理一个且仅一个时使用DAO。网关中的所有方法通常都会返回CF查询对象。 CF的效率太低,无法创建大量的DAO对象,在我们看来,CF中的查询对象非常灵活,所以我们很乐意使用它。

编码时,子类CustomerGateway.cfc是唯一实例化和使用的子类。但是,它扩展的基类有一些非常有用的通用函数,例如getFieldListByProperty()基于传递的参数将返回特定字段(即表列)的特定属性(即列值),例如:

myGateway.getFieldListByProperty(property="status", value="1", fieldList="customerName,customerID", orderBy="createdOn") />

该调用将返回状态为1的所有客户的'customerName'和'customerID'值,按创建日期排序。代码也针对SQL注入进行了强化并经过验证,因此抛出了合理的异常。

此功能将提供99%(我们希望!)您在桌面上进行的多记录查询。如果您需要更复杂的查询,那么CustomerGateway.cfc可供您添加功能。

最后,我们允许您向CustomerGateway CFC 添加功能,因为如果更改customers表(例如添加列),则需要重新创建表格,并且覆盖Customers.cfcCustomersGatewayBase.cfc。但是,您的自定义代码(如果有)在子类中是安全的。

无论如何,这可能稍微偏离主题,但我确信有人可能会发现我们的经验很有用。