Вопрос

Я строю объект для поиска заказов в моей базе данных. Есть множество возможных параметров, которые пользователь может установить, и они могут установить столько, сколько нужно для каждого поиска. Я создал методы установки для сбора всех параметров, необходимых для поиска.

Мой вопрос такой. Что будет "наилучшей практикой"

<Ол>
  • Сохранение параметров и создание предложения WHERE , когда вызывается метод doSearch
  • Создание предложения WHERE в качестве параметров
  • Я хотел бы понять причину любой рекомендации.

    Обратите внимание, что объект устанавливается для каждого поиска, поэтому мне не нужно беспокоиться о повторном поиске с другими параметрами.

    Это было полезно?

    Решение

    Вы должны отделить код для поиска вашего заказа от кода, который строит SQL. SQL должен быть встроен в производную (или производная стратегия ) OrderSearch класс. После того как вы сделали это разделение, когда вы создадите SQL, на самом деле не имеет значения.

    Чтобы сделать это немного проще. Если у вас есть класс с именем OrderSearch , в котором есть несколько методов-установщиков для критериев поиска, вы хотите иметь подкласс с именем OrderSearchSQLBuilder . Обратите внимание, что подкласс зависит от базового класса, и что базовый класс не зависит от подкласса. Это очень важно. Эта независимость позволяет не учитывать, встроен ли SQL в методы установки или в метод поиска. См. Принцип инверсии зависимостей (DIP) .

    Если у вас есть этот вид разделения, вы можете заменить производную другими стратегиями. Например, если вы хотите протестировать свое приложение, не подключая его к базе данных SQL, вы можете создать фиктивную встроенную базу данных и создать производную от OrderSearch , которая работает с этой фиктивной базой данных. Остальная часть приложения будет в блаженном неведении, и тогда ваши тесты будут независимы от ужасов соединений с базой данных, ранее существовавших данных и т. Д.

    Другие советы

    В вашем методе просто используйте параметры в вашем динамическом SQL, который выполняет поиск. Таким образом, предложение where создается непосредственно перед запуском SQL. Вы просто передадите параметры поиска в свой метод в качестве аргументов.

    Примерно так ...

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

    Не создавайте предложение where, пока оно не понадобится для выполнения поиска. Вы можете получить пользовательский интерфейс, который передает параметры в итерациях, и вы не знаете, когда у вас все есть. Кроме того, вы никогда не сможете выполнить поиск, так что зачем беспокоиться о предложении where.

    Я не думаю, что это имеет большое значение, но я думаю, что лучше создать предложение WHERE, когда вы выполняете поиск. Я не думаю, что сеттер должен отвечать за параметр, добавляемый в строку предложения WHERE.

    В базе данных SQLServer более эффективно включать все параметры в предложение where, а не создавать его на лету. Затем имейте индекс базы данных, который включает все столбцы, по которым вы будете искать. Это гарантирует, что индекс всегда используется при выполнении оператора.

    Не совсем похоже, что ваша абстракция совершенно правильная.

    Поиск может быть лучше в качестве метода "заказов" объект. передать параметры в функцию поиска и создать запрос вручную, как предложенный рус . Все, что относится к заказам, а не к поиску, может быть установлено в методе init заказов.

    Возможно, вы захотите построить объект поиска заказов, но это должно быть сделано с помощью объекта заказов, чтобы ваш интерфейсный код был простым.

    Вариант 1 - ваш лучший выбор. Вариант 2 звучит опасно. Что если параметр обновляется? Как заменить его в предложении WHERE?

    Я бы сделал что-то вроде этого:

    <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>
    
    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top