我编写了一个网关来从我的数据库中获取结果集。如何将每一行存储在一个单独的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等)。什么是最佳实践,专业人士做什么?
答案 0 :(得分:3)
专业人员只使用一种模式用于数据库访问层。 DAO和Gateway的使用是一个误称,我不确定它从哪里开始,但似乎只存在于ColdFusion人群中。 DAO和网关模式几乎可以提供相同的功能,但我认为在讨论数据库交互时,DAO更符合要求。
DAO应该包括CRUD方法的功能以及返回的记录集。由于CRUD和基本记录集具有高度重复性,因此我使用代码生成器为此交互创建代码,然后自定义我需要的内容。这是条件逻辑选择所需记录的好地方。
正如Aaron所提到的,由于创建对象的性能开销,在ColdFusion中为数据库中的一组记录返回一个对象数组是不可行的。我通常只在我的视图中使用从DAO返回的基本查询。但是,如果我正在建模的东西在视图中需要一些行为,那么我将使用类似于Peter Bell所做的事情将查询放在一个对象中。
答案 1 :(得分:2)
条件逻辑可以进入网关或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.cfc
和CustomersGatewayBase.cfc
。但是,您的自定义代码(如果有)在子类中是安全的。
无论如何,这可能稍微偏离主题,但我确信有人可能会发现我们的经验很有用。