Pregunta

Estoy creando un objeto para buscar órdenes en mi base de datos. Hay una serie de posibles parámetros que el usuario puede configurar, y pueden establecer tantos como desee para cada búsqueda. He creado métodos de configuración para recopilar todos los parámetros necesarios para la búsqueda.

Mi pregunta es la siguiente. ¿Qué sería " mejores prácticas "

  1. Almacenar los parámetros y crear la cláusula WHERE cuando se llama al método doSearch
  2. Construyendo la cláusula WHERE como se establecen los parámetros

Me gustaría entender la razón detrás de cualquier recomendación.

Tenga en cuenta que el objeto está insinuado para cada búsqueda, por lo que no tengo que preocuparme por una segunda búsqueda con diferentes parámetros.

¿Fue útil?

Solución

Debe separar el código para su búsqueda de pedido del código que construye el SQL. El SQL se debe construir en un derivado (o Strategy derivado) del OrderSearch clase. Una vez que haya hecho esta separación, realmente no importa cuando construye el SQL.

Para hacer esto un poco más simple. Dada una clase llamada OrderSearch que tiene un montón de métodos de establecimiento para los criterios de búsqueda, le gustaría tener una subclase llamada OrderSearchSQLBuilder . Observe que la subclase depende de la clase base y que la clase base es independiente de la subclase. Esto es muy importante. Esta independencia le permite ignorar si el SQL está integrado en los métodos de establecimiento o en el método de búsqueda. Consulte El principio de inversión de dependencia (DIP) .

Una vez que tenga este tipo de separación, puede reemplazar el derivado con otras estrategias. Por ejemplo, si desea probar su aplicación sin conectarlo a la base de datos SQL, puede crear una base de datos in-ram ficticia y crear un derivado de OrderSearch que se ocupe de esa base de datos ficticia. El resto de la aplicación sería felizmente inconsciente, y sus pruebas serían independientes de los horrores de las conexiones de la base de datos, los datos preexistentes, etc.

Otros consejos

En su método, simplemente use los parámetros en su SQL dinámico que realiza la búsqueda. De esa manera, la cláusula where se construye justo antes de que se ejecute el SQL. Simplemente pasará los parámetros de búsqueda a su método como argumentos.

Algo como esto ...

<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>

No cree la cláusula where antes de que sea necesaria para ejecutar la búsqueda. Puede terminar con una interfaz de usuario que alimenta parámetros en iteraciones y no sabe cuándo lo tiene todo. Además, nunca puede ejecutar la búsqueda, así que, ¿por qué preocuparse por la cláusula where?

No creo que haga mucha diferencia, pero creo que parece una mejor práctica construir la cláusula WHERE cuando haces una búsqueda. No creo que deba ser responsabilidad de un configurador que un parámetro se agregue a una cadena de cláusula WHERE en alguna parte.

En una base de datos SQLServer es más eficiente incluir todos los parámetros en la cláusula where en lugar de construirlo sobre la marcha. Luego, tenga un índice de base de datos que incluya todas las columnas en las que buscará. Esto garantiza que el índice siempre se use al ejecutar la declaración.

No suena muy bien como si tu abstracción fuera correcta.

La búsqueda puede ser mejor como método de un " pedidos " objeto. pase los parámetros a la función de búsqueda y genere la consulta manualmente como russ sugirió . Cualquier cosa que sea específica de los pedidos en lugar de la búsqueda se puede establecer en el método de inicio de pedidos.

Es posible que desee compilar un objeto de búsqueda de pedidos, pero esto debe hacerse a través de un objeto de pedidos, para que su código de usuario sea sencillo.

La opción 1 es tu mejor apuesta. La opción 2 suena peligrosa. ¿Qué pasa si se actualiza un parámetro? ¿Cómo lo reemplazas en tu cláusula WHERE?

Haría algo como esto:

<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 bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top