Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/86.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Grails—存储服务将使用的sql_Sql_Grails - Fatal编程技术网

Grails—存储服务将使用的sql

Grails—存储服务将使用的sql,sql,grails,Sql,Grails,我正在编写一个Grails应用程序,它将主要使用由服务支持的端点。这些服务将从各种后端数据库检索数据(即,不通过域类和GORM)。我想将我的服务用来获取web服务数据的sql存储在外部文件中。 我正在寻找以下方面的建议: 保存文件的最佳位置(例如,我想把它们放在grails app/sql等明显的地方)和最佳格式(例如,xml、configslurper等)在哪里 提取sql文本的最佳方法,这样执行sql的我的服务就不需要知道从何处或如何获取它们。服务将只提供一个sqlid并获取sql 您是否考

我正在编写一个Grails应用程序,它将主要使用由服务支持的端点。这些服务将从各种后端数据库检索数据(即,不通过域类和GORM)。我想将我的服务用来获取web服务数据的sql存储在外部文件中。 我正在寻找以下方面的建议:

  • 保存文件的最佳位置(例如,我想把它们放在grails app/sql等明显的地方)和最佳格式(例如,xml、configslurper等)在哪里

  • 提取sql文本的最佳方法,这样执行sql的我的服务就不需要知道从何处或如何获取它们。服务将只提供一个sqlid并获取sql


  • 您是否考虑过使用Grails GORM和HSQLDB数据库来存储要执行的SQL?然后,您可以为包含该SQL服务的每个服务输入一条记录,并使用普通的Grails GORM函数检索它。您可以生成一组默认的控制器和视图,允许您编辑SQL。如果要将SQL存储在外部文件中,可以在web应用程序目录中创建一个名为SQL的子目录,然后将SQL语句存储为文本文件。您可以创建一个采用服务名称的类,加载包含SQL的关联文本文件并返回该文件的内容。如果不知道SQL的复杂程度,我就说不出最好的格式是什么。如果处理没有参数替换的正常select语句,最好是纯文本。如果您要处理更复杂的带有替换和多个查询的SQL,您可能需要使用XML。

    我最近在做一个项目,我需要做一些类似的事情。我创建了以下目录来存储sql文件:

    /grails-app/conf/sql

    例如,有一个文件./grails app/conf/sql/hr/FIND_PERSON_BY_ID.sql,其内容如下:

    select a.id
    , a.first_name
    , a.last_name 
    from person 
    where id = ?
    
    我创建了一个SqlCatalogService类,该类将加载该目录(和子目录)中的所有文件,并将文件名(减去扩展名)和文件文本存储在映射中。该服务有一个get(id)方法,该方法返回缓存在映射中的sql文本。由于存储在grails app/conf中的文件/目录放在类路径中,因此SqlCatalogService使用以下代码读取文件:

    ....
    ....
    Map<String,String> sqlCache = [:]
    ....
    ....
    void loadSqlCache() {
        try {
            loadSqlCacheFromDirectory(new File(this.class.getResource("/sql/").getFile()))
        } catch (Exception ex) {
            log.error(ex)
        }       
    }
    
    void loadSqlCacheFromDirectory(File directory) {
        log.info "Loading SQL cache from disk using base directory ${directory.name}"
        synchronized(sqlCache) {
            if(sqlCache.size() == 0) {
                try {  
                    directory.eachFileRecurse { sqlFile ->
                        if(sqlFile.isFile() && sqlFile.name.toUpperCase().endsWith(".SQL")) {
                            def sqlKey = sqlFile.name.toUpperCase()[0..-5]
                            sqlCache[sqlKey] = sqlFile.text
                            log.debug "added SQL [${sqlKey}] to cache"
                        }
                    }                                   
                } catch (Exception ex) {
                    log.error(ex)
                }       
            } else {
                log.warn "request to load sql cache and cache not empty: size [${sqlCache.size()}]"
            }
        }
    }
    
    String get(String sqlId) {
        def sqlKey = sqlId?.toUpperCase()
        log.debug "SQL Id requested: ${sqlKey}"
        if(!sqlCache[sqlKey]) {
            log.debug "SQL [${sqlKey}] not found in cache, loading cache from disk"
            loadSqlCache()
        }
        return sqlCache[sqlKey]
    }
    
    目前,我们只有几个sql语句,因此在映射中存储所有文本不是问题。如果要存储大量sql文件,您可能需要考虑使用Ehcache之类的工具,并定义逐出策略(即最近使用最少或使用最少),只在内存中存储使用最多的sql文件,并在需要时将其余文件保留在磁盘上


    在此之前,我考虑过使用GORM并将sql文本存储在数据库中。但是,我们决定将sql保存在文件中使开发变得更容易,因为我们几乎可以直接从sql工具将sql保存到文件中(用问号替换硬代码参数),并且能够让我们的修订控制系统跟踪更改。我并不是说上述服务是处理这一问题的最有效或最正确的方法,但到目前为止,它满足了我们的需要。

    如果我有足够的代表,我会+1。我考虑过使用GORM并使用域类将sql存储在db中。然而,我认为存储在文件中可能是更好的方法,并允许我使用源代码管理系统来保存修订历史。我希望能收到过去可能做过这件事的人的来信,所以在我接受任何答复之前,我想再等几天。谢谢你的回答。
    class PersonService {
    
        def hrDataSource
        def sqlCatalogService
    
        private static final String SQL_FIND_PERSON_BY_ID = "FIND_PERSON_BY_ID"
    
        Person findPersonById(String personId) {
            try {
                def sql = new groovy.sql.Sql(hrDataSource)
                def row = sql.firstRow(sqlCatalogService.get(SQL_FIND_PERSON_BY_ID), [personId])
                row ? new Person(row) : null
            } catch (Exception ex) {
                log.error ex.message, ex
                throw ex
            }
        }
    }