Pergunta

Eu estou construindo um objeto para procurar ordens no meu banco de dados. Há um monte de possíveis parâmetros que o usuário pode definir, e eles podem definir quantos seguida, quer para cada pesquisa. Criei setter métodos para recolher todos os parâmetros necessários para a pesquisa.

A minha pergunta é esta. O que seria "melhor prática"

  1. Armazenar os parâmetros, e construir a cláusula WHERE quando o método doSearch é chamado
  2. Construindo a cláusula WHERE como parâmetros são definidos

Eu gostaria de entender a razão por trás de qualquer recomendação.

Note que o objeto é instatiated para cada pesquisa, então eu não precisa se preocupar com uma segunda pesquisa com parâmetros diferentes.

Foi útil?

Solução

Você deve separar o código para a sua pesquisa ordem do código que constrói o SQL. O SQL deve ser construído em um derivado (ou Estratégia derivado) da classe OrderSearch. Depois de ter feito esta separação, não importa realmente quando você construir o SQL.

Para tornar isto um pouco mais claro. Dada uma classe OrderSearch chamado que tem um monte de métodos setter para os critérios de pesquisa, você gostaria de ter uma subclasse chamada OrderSearchSQLBuilder. Observe que a subclasse depende da classe de base, e que a classe base é independente da subclasse. Isto é muito importante. Esta independência permite-lhe ignorar se o SQL é construída nos métodos setter, ou no método de pesquisa. Consulte A inversão de dependência Princípio (DIP) .

Uma vez que você tem esse tipo de separação, você pode substituir o derivado com outras estratégias. Por exemplo, se você quiser testar sua aplicação sem a conexão com o banco de dados SQL, você pode criar um boneco de banco de dados na memória RAM e criar um derivado do OrderSearch que lidava com esse banco de dados fictício. O resto da aplicação seria alegremente inconscientes, e seus testes, então, seria independente dos horrores de conexões de banco de dados, pré-existente de dados, etc.

Outras dicas

Em seu método, basta usar os parâmetros em sua SQL dinâmica que faz a pesquisa. Dessa forma, a cláusula WHERE é construído pouco antes do SQL ficando prazo. Você vai simplesmente passar os parâmetros de busca em seu método como argumentos.

Algo assim ...

<cffunction name="getByAttributesQuery" access="public" output="false" returntype="query">
    <cfargument name="id" type="numeric" required="false" />
    <cfargument name="userName" type="string" required="false" />
    <cfargument name="firstName" type="string" required="false" />
    <cfargument name="lastName" type="string" required="false" />
    <cfargument name="createdAt" type="date" required="false" />
    <cfargument name="updatedAt" type="date" required="false" />
    <cfargument name="orderby" type="string" required="false" />

    <cfset var qList = "" />        
    <cfquery name="qList" datasource="#variables.dsn#">
        SELECT  
            id,
            userName,
            firstName,
            lastName,
            createdAt,
            updatedAt
        FROM    users
        WHERE       0=0
    <cfif structKeyExists(arguments,"id") and len(arguments.id)>
        AND id = <cfqueryparam value="#arguments.id#" CFSQLType="cf_sql_integer" />
    </cfif>
    <cfif structKeyExists(arguments,"userName") and len(arguments.userName)>
        AND userName = <cfqueryparam value="#arguments.userName#" CFSQLType="cf_sql_varchar" />
    </cfif>
    <cfif structKeyExists(arguments,"firstName") and len(arguments.firstName)>
        AND firstName = <cfqueryparam value="#arguments.firstName#" CFSQLType="cf_sql_varchar" />
    </cfif>
    <cfif structKeyExists(arguments,"lastName") and len(arguments.lastName)>
        AND lastName = <cfqueryparam value="#arguments.lastName#" CFSQLType="cf_sql_varchar" />
    </cfif>
    <cfif structKeyExists(arguments,"createdAt") and len(arguments.createdAt)>
        AND createdAt = <cfqueryparam value="#arguments.createdAt#" CFSQLType="cf_sql_timestamp" />
    </cfif>
    <cfif structKeyExists(arguments,"updatedAt") and len(arguments.updatedAt)>
        AND updatedAt = <cfqueryparam value="#arguments.updatedAt#" CFSQLType="cf_sql_timestamp" />
    </cfif>
    <cfif structKeyExists(arguments, "orderby") and len(arguments.orderBy)>
        ORDER BY #arguments.orderby#
    </cfif>
    </cfquery>

    <cfreturn qList />
</cffunction>

Não construir a cláusula WHERE antes que é necessário para executar a pesquisa. Você pode acabar com uma interface de usuário que alimenta parâmetros em iterações, e você não sabe quando você tem tudo. Além disso, você nunca pode executar a pesquisa, então por que se preocupar com a cláusula where.

Eu não acho que isso faz muita diferença, mas eu acho que parece melhor prática para construir a cláusula WHERE quando você doSearch. Eu não acho que deveria ser da responsabilidade de um setter para um parâmetro para adicionar a uma ONDE algum lugar corda cláusula.

Em um banco de dados SQLServer é mais eficiente para incluir todos os parâmetros na cláusula onde, em vez de construí-lo na mosca. Então, um índice de banco de dados que inclui todas as colunas que você vai pesquisar. Isso garante que o índice é sempre usado quando executar a instrução.

dosn't bastante soar como sua abstração é muito certo.

Pesquisa pode ser melhor como um método de um objeto de "ordens". passar os parâmetros para a função de pesquisa e construir a consulta manualmente, como russ sugeriu . Tudo o que é específico para ordens em vez da busca pode então ser definidos sob as ordens método init.

É possível que você pode querer construir procurar um ordens objeto, mas isso deve ser feito através de um ordens objeto, para manter a sua simples código de front-end.

A opção 1 é a sua melhor aposta. Opção 2 parece perigoso. E se um parâmetro é atualizado? Como você substituí-lo na sua cláusula WHERE?

eu faria algo assim:

<cffunction name="doSearch" access="public" output="false" returntype="query">        
    <cfset var qList = "" />
    <cfquery name="qList" datasource="#variables.dsn#">
       SELECT
           ...
       FROM
           ...
       WHERE 0=0 
         <cfif len(getID())>
           AND id = <cfqueryparam value="#getID()#" CFSQLType="cf_sql_integer" />
         </cfif>       
         <cfif len(getUserName())>
           AND userName = <cfqueryparam value="#getUserName()#" CFSQLType="cf_sql_varchar" />
         </cfif>
    </cfquery>
    <cfreturn qList />
</cffunction>
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top