【问题标题】:Return Query Results To The View In Grails将查询结果返回到 Grails 中的视图
【发布时间】:2014-09-05 02:11:44
【问题描述】:

我想执行一条 sql 语句并将结果返回到 Grails 中的视图。澄清一下,我不想返回域对象并将它们显示在视图上。我有一个简单的查询,我要在其中加入两个表,我只想将结果传递给视图进行显示。

这是我认为的代码:

<%@ page contentType="text/html;charset=UTF-8" %>
<html>
<head>
    <meta name='layout' content='main'/>
    <title></title>
</head>

<body>

<div id = 'overall'>


    <g:if test="${queryResultMap.size() > 0}">

    <table border="1">

        <thead>
        <tr>
            <th>Banner ID</th>
            <th>PIDM</th>
            <th>Term</th>
            <th>Processed Indicator</th>
        </tr>
        </thead>
        <tbody>
        <g:each in="${queryResultMap}" status="i" var="thisRecord">
            <tr>
                <td>${thisRecord.SPRIDEN_ID}</td>
                <td>${thisRecord.SFRWDRL_PIDM}</td>
                <td>${thisRecord.SFRWDRL_TERM_CODE}</td>
                <td>${thisRecord.SFRWDRL_PROCESSED_IND}</td>
            </tr>

        </g:each>
        </tbody>

    </table>
    </g:if>
    <g:else>
        No records were found to update.
    </g:else>



</div>

</body>
</html>

这是我的控制器中的代码:

    //Create our database connection...
    Sql sqlStatement = new Sql(dataSource)

    //Here is my simple query 
    def sqlString =
             "SELECT S.SPRIDEN_ID, " +
                    "D.SFRWDRL_PIDM, " +
                    "D.SFRWDRL_PROCESSED_IND, " +
                    "D.SFRWDRL_USER, " +
                    "D.SFRWDRL_USER_ID, " +
                    "D.SFRWDRL_ACTIVITY_DATE, " +
                    "D.SFRWDRL_TERM_CODE " +
            "FROM SATURN.SPRIDEN S, SATURN.SFRWDRL D \n" +
                    "WHERE S.SPRIDEN_PIDM = \'" + pidm + "\' " +
                    "AND S.SPRIDEN_CHANGE_IND IS NULL " +
                    "AND S.SPRIDEN_PIDM = D.SFRWDRL_PIDM " +
                    "AND D.SFRWDRL_TERM_CODE = '" + term + "\' "

    def returnList = []

    //Put out query results into the queryResults array...
    sqlStatement.eachRow(sqlString){
        returnList << it.toRowResult()
    }


    //Close our database connection...
    sqlStatement.close()


    println returnList

    return [queryResultMap: returnList]

当我运行它时,我在控制台中看到以下内容,因此我知道 returnList 具有来自查询的结果列表:

Error 500: Internal Server Error

URI
    /FinAid-WithdrawalProcessIndicatorUpdate/sfrwdrl/processWithdrawalIndicator
Class
    groovy.lang.MissingPropertyException
Message
    No such property: SPRIDEN_ID for class: edu.unm.processindicator.Sfrwdrl

Grails 的行为就像它正在寻找一个域对象 (edu.unm.processindicator.Sfrwdrl),而我正在尝试显示 returnList 中的一个值(这些不是域对象)。而且我知道 returnList 数组有值,因为这是我在 return 语句之前将输出打印到控制台时看到的:

[SPRIDEN_ID:101638052, SFRWDRL_PIDM:1638080, SFRWDRL_PROCESSED_IND:Y, SFRWDRL_USER:P_SZPGF02_MAIN, SFRWDRL_USER_ID:null, SFRWDRL_ACTIVITY_DATE:2014-02-05 14:15:46.0, SFRWDRL_TERM_CODE:201410]

如果我能找到一些具体的例子来展示如何返回查询结果并将它们显示在一个非常感激的视图中。或者......我是否只是把这一切都搞错了,如果我想显示来自多个表的信息,我需要在我的域对象中定义一对多的关系?我正在尝试做的事情在 Grails 中是否可行?我已经进行了大量搜索,并一直在查看 Grails 文档中的标签信息,但我无法找到答案。提前致谢!

【问题讨论】:

  • 如果这是一个包含两个表的简单查询,为什么要直接使用 SQL?
  • 我的组织即将真正开始使用 Grails,我们现在正处于探索阶段。我们将使用不是我们设计的供应商提供的数据库。将来,有时我们会希望执行具有许多连接的复杂查询。这个问题不仅仅是我问如何解决这个问题。我们需要知道 Grails 是否真的可以返回简单的查询结果(而不是域对象),因为它会影响我们开发人员编码方式的标准......

标签: sql grails view controller gsp


【解决方案1】:

首先,您在评论中提出的问题是“Grails 真的可以返回简单的查询结果吗?”。答案是:绝对是的。

使用 Groovy 的Sql class,您可以很容易地做到这一点。但是,您似乎让自己的事情变得更加困难。

从您以易于 SQL 注入的方式构建 SQL 的事实开始。我强烈建议您考虑至少使用 GString 并进行变量替换。

接下来,在您的示例中,无需将查询结果放入returnList。只需调用 .executeQuery 并将 ResultSet 返回到您的 GSP 即可。

最后,在您的 GSP 中显示结果。鉴于结果中的非标准 bean 名称列,最好在从 ResultSet 访问它们时使用引号引用它们。例如:

<td>${thisRecord.'SPRIDEN_ID'}</td>

这样就不会混淆您希望 Groovy 做什么。只需按该名称访问该属性。

总而言之,在处理无法或不希望使用 ORM 的第三方或遗留数据库时,可以使用 Grails。我个人在这方面取得了巨大的成功。

【讨论】:

  • 谢谢你 Joshua - 我们在这方面很牛逼,你的建议 - 特别是 SQL 注入 - 让我们对一些事情大开眼界。感谢您抽出宝贵时间回复!我确实弄清楚了根本问题是什么,并将其发布在下面。如果我实际上发布了控制器中的所有代码,我相信你会发现我的错误。再次感谢。
【解决方案2】:

我发现我的代码确实有效。我得到的错误如下:

Error 500: Internal Server Error

URI
    /FinAid-WithdrawalProcessIndicatorUpdate/sfrwdrl/processWithdrawalIndicator
Class
    groovy.lang.MissingPropertyException
Message
    No such property: SPRIDEN_ID for class: edu.unm.processindicator.Sfrwdrl

我最初发布的控制器代码是我实际操作的缩短版本。我最初是使用 returnList 数组来抓取域对象:

private void updateSfrwdrlAndAddToList(pidm, unmId, term, ArrayList returnList)
    {
        def results

        results = Sfrwdrl.where
        {
            sfrwdrlTermCode == term
            sfrwdrlPidm == pidm
            sfrwdrlProcessedInd == "Y"
        }

        for (i in results)
        {
            i.sfrwdrlProcessedInd = 'N'
            i.sfrwdrlActivityDate = new Date()
            i.sfrwdrlUserId = unmId

            returnList.add(i)
        }

    }         

然后我最终在上面的代码中重用了该 returnList。在上面的代码中,我定义了变量,但在我的原始代码中,我认为执行以下操作会清除数组,以便我可以重用它:

returnList = []

sqlStatement.eachRow(sqlString){
                returnResults << it.toRowResult()
            }

            println 'Here are the results!'
            println returnResults

            sqlStatement.close()

            return [returnMap: returnResults]

最初创建 ArrayList 时,我认为它的类型一定是我的域对象(edu.unm.processindicator.Sfrwdrl)。然后我错误地将查询结果放在该列表中(属于 GroovyRowResult 类型。

将 returnList Array(类型为 Sfrwdrl)发送到其中包含 GroovyRowResult 对象的视图是导致问题的原因。该视图期望对象的类型为 Sfrwdrl(我的域对象)。

我现在在视图中看到我的查询结果。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-02-26
    • 2016-11-16
    • 1970-01-01
    • 1970-01-01
    • 2013-10-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-14
    相关资源
    最近更新 更多