web-dev-qa-db-ja.com

MVC設定でSQLを使用するときに、保守不可能なコードを回避する方法は?

製品のリストをユーザーに提示したいと思います。このリストにはページ番号が付けられ、ユーザーは製品IDまたは製品名の昇順または降順でソートできます。

MVC設定を使用しています。モデルのデータベースにクエリを実行します。

データベースにクエリを実行する関数をどのように記述しますか?いくつかのオプションが考えられますが、すべてに欠点があります。

  1. 並べ替え列と並べ替え方向の可能な組み合わせごとに1つの関数があり、それぞれに異なるクエリが含まれています。

    func GetProductsOrderByIdAsc() []*Product { … }
    func GetProductsOrderByIdDesc() []*Product { … }
    func GetProductsOrderByNameAsc() []*Product { … }
    func GetProductsOrderByNameDesc() []*Product { … }
    

    これは、「重複コード」とも呼ばれる、ほぼ同一のSQLクエリが多数発生するため、明らかに保守不可能です。

  2. SQLの文字列を連結します。

    func GetProducts(orderBy string, orderDirection string) []*Product {
        return db.query(`
              SELECT id, name, description
                FROM products
            ORDER BY ` + orderBy + ` ` + orderDirection + `
        `)
    }
    

    これは、すぐに混乱するため、エレガントではなく、読み取り不能で、保守できません。ページ付けとフィルタリングを追加することを想像してください。これらは値ではなく列であるため、パラメータバインディングはここでは機能しません。

  3. SQLではなくGoで並べ替え、フィルタリング、ページ分割を行います。これでコードの重複の問題は解決しますが、膨大な数のレコードがある場合、パフォーマンスの問題になる可能性があります。

この問題を解決する通常の具体的な方法は何ですか?理想的には、重複したコード、醜いクエリ合成、大きな非効率性はありません。

4
rightfold

私はGoの経験はありませんが、質問のタイトルはGoに限定されていることを示していないため、一般的な意味でお答えします。

MVCでSQLに取り組む最良の方法は、モデルにORMを使用することです。一部のクエリはORMを使用すると遅くなる場合があります。その場合、別の関数に分離される可能性があります。

どうしても自分でクエリを作成する必要がある場合(利用可能なORM実装がない、またはパフォーマンスを調整する必要があるクエリなど)、#2と同様に、既存の堅牢なテンプレートを使用して、置換用のパラメーターを期待するテンプレートを作成します。エンジン。

SQLインジェクションを回避するために、SQLのクエリパラメータは常にエスケープする必要があることに注意してください。

6
Michael Kruglos

私の入力はSQL句ではなくブール値などですが、ほとんどオプション#2を使用します。次に、関数はこれらのパラメーターからインテリジェントにクエリを形成します。それが気に入らない場合は、すべてのオプションの値を含む配列を受け入れるようにしてください。

それは持っている混乱することはありません。適切に堅牢にコーディングすれば、見た目も実行方法も問題ありません。

SQLをDBに配置し、ストアドプロシージャとしてモデルに公開します。これを直接実行するか、呼び出しているようなAPIを提供するよりフレンドリーなサービスレイヤー(Webサービスを使用するなど)でそれらをラップできます。サードパーティのWeb API。つまり、すべてのDBを使用できるようにするのではなく、どのような種類のデータAPIを公開するかを考える必要があるということです。これにより、コードを分離して保守しやすくなります。また、誰かがWebサーバーをハッキングした場合(またはいつ!)のセキュリティが大幅に向上することも意味します。

0
gbjbaanb