クエリからレコードをDAOに入れる方法は?
-
06-07-2019 - |
質問
データベースから結果セットを取得するためのゲートウェイを作成しました。すべてのレコードをさらに操作できるように、すべての行を個別の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など)。ベストプラクティスは何ですか、プロは何をしますか?
解決
プロは、データベースアクセスレイヤーに1つのパターンのみを使用します。 DAOとGatewayの両方を使用することは、どこから始めたのか本当にわからないという誤った名前ですが、ColdFusionの群衆にのみ存在するようです。 DAOとGatewayのパターンはほぼ同じ機能を果たすことができますが、データベースの相互作用について話すときは、DAOの方がより適切だと思います。
DAOには、CRUDメソッドに加えてレコードセットを返す機能が含まれている必要があります。 CRUDと基本的なレコードセットは非常に反復性があるため、コードジェネレーターを使用してこの対話用のコードを作成し、必要なものをカスタマイズします。これは、必要なレコードを選択するための条件ロジックに適した場所です。
アーロンが述べたように、データベースの一連のレコードのオブジェクトの配列を返すことは、オブジェクトを作成するパフォーマンスのオーバーヘッドのため、ColdFusionでは実行不可能です。私は通常、ビューでDAOから返された基本的なクエリを使用します。ただし、モデリングしているものがビューで何らかの動作を必要とする場合は、Peter Bellが行うことと同様の方法を使用して、オブジェクトにクエリを配置します。
他のヒント
Peter Bellは、数か月前に、このシンプルなフレームワークを使用して複数のレコードを取得し、一度に1つのレコードを反復処理できるIterating Business Object CFCのリリースについて素晴らしいプレゼンテーションを行いました。 http://ibo.riaforge.org/ 。オブジェクトの生成でCFが少し速くなるまで、オブジェクトの単一のインスタンスをリサイクルしてプロパティを再設定するのが最善です。おそらく、これはDAOに一度に1つのレコードをロードするのに役立ちます。
条件付きロジックは、ゲートウェイまたはManager CFCに配置できます。通常、投稿で概説したロジックのような単純なロジックをCFCに直接含めます。
ちょっとしたアドバイスとして、arguments.distinctを必須とせず、if(structKeyExists(arguments、&quot; distinct&quot;)){do something}で簡単なチェックを行うことをお勧めします。
よろしく、
-アーロン・グリーンリー
私たちの会社では、RDSや他の古いもの(CFPowerToolsを覚えている人はいますか?)を介してAdobe CF DAO作成者を試して、数か月間このことについて長く一生懸命考えました。
最終的に、独自の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は、1つだけを処理するときに使用されます。通常、ゲートウェイのすべてのメソッドは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 only に関数を追加できます。これは、customersテーブルを変更する(列を追加するなど)場合、テーブルを再作成する必要があるためです。 thaは Customers.cfc
と CustomersGatewayBase.cfc
を上書きします。ただし、カスタムコード(存在する場合)はサブクラスで安全です。
とにかく、これは少し話題から外れているかもしれませんが、誰かが私たちの経験を役に立つと思うかもしれないと思いました。