我有一个查询,我按照我想要的方式调用列,我不能使用查询的ColumnList,因为它按字母顺序排序列,另一件事我需要获取查询的特定行及其关联的列结构:
所以这是我的功能,我试图以我想要的方式带来列:
<cffunction name="rowToStruct" access="public" returntype="struct" output="false">
<cfargument name="queryObj" type="query" required="true" />
<cfargument name="row" type="numeric" required="true" />
<cfset var returnStruct = structNew()>
<cfset var colname = "">
<cfset arguments.queryObj = arrayToList(arguments.queryObj.getMeta().getColumnLabels())>
<cfloop list="#arguments.queryObj#" index="colname">
<cfset "returnStruct.#colname#" = arguments.queryObj[colname][arguments.row]>
</cfloop>
<cfreturn returnStruct/>
</cffunction>
在上述更改之前,函数如下所示:
<cffunction name="rowToStruct" access="public" returntype="struct" output="false">
<cfargument name="queryObj" type="query" required="true" />
<cfargument name="row" type="numeric" required="true" />
<cfset var returnStruct = structNew()>
<cfset var colname = "">
<cfloop list="#arguments.queryObj.columnList#" index="colname">
<cfset "returnStruct.#colname#" = arguments.queryObj[colname][arguments.row]>
</cfloop>
<cfreturn returnStruct/>
</cffunction>
我的一个人错误地给我一个错误:
您试图将类型为java.lang.String的标量变量取消引用为具有成员的结构。
答案 0 :(得分:2)
getMetadata()
函数按原始语句中定义的顺序返回列。文件:GetMetaData
。
我无法理解为什么您的代码会产生错误,尽管我这样做:
<cfset returnStruct[colname] = arguments.queryObj[colname][arguments.row]>
您是否可以使用屏幕上显示的确切错误更新您的问题,包括其关注的代码以及相关的行号(如果尚未启用,则切换强健例外处理)
答案 1 :(得分:2)
出错的原因是您要覆盖传递给函数的查询对象。新代码将arguments.queryObj
的值重置为一个简单的字符串:
<cfset arguments.queryObj = arrayToList(arguments.queryObj.getMeta().getColumnLabels())>
稍后在代码中,您尝试使用arguments.queryObj
变量,就好像它仍然是查询对象一样。显然,这会导致错误,因为变量现在代表一个字符串:
<cfset "returnStruct.#colname#" = arguments.queryObj[colname][arguments.row]>
解决方案是使用不同的变量来存储列名列表。由于它也是函数局部变量,因此请务必使用local
或var
正确定位。
也就是说,Adam mentioned in his answer,使用其中一个内置函数已经支持您需要的功能。因此,确实不需要使用coldfusion.sql.QueryTable
查询类IMO的未记录方法。 GetMetaData(queryObject)
返回包含两个键的结构数组:Name
(列名),IsCaseSensitive
(布尔值)。要遍历它,请使用&#34;数组&#34;循环而不是&#34;列表&#34;循环:
...
<cfset var returnStruct = {}>
<cfset var col = "">
<cfset var colArray = getMetaData(arguments.queryObj)>
<cfloop array="#colArray#" index="col">
<cfset returnStruct[col.Name] = arguments.queryObj[col.Name][arguments.row]>
</cfloop>
...
更新1:
我不能使用查询的ColumnList,因为它对列进行排序 alphabatically
这里更大的问题是CF结构没有订购。即使您按正确的顺序将值添加到结构中,也不会保留该顺序。您需要在调用代码中解决该问题(即使用GetMetaData(query)
)或让cffunction返回有序列名和行数据。后者似乎有点多余,但这完全取决于您在应用程序中使用该函数的方式。
更新2:
如果你真的需要一个排序结构..还有一些java类维护插入顺序,比如LinkedHashMap。由于它实现了java.util.Map,因此它可以是used like a CF structure(在大多数情况下)。
<cfset var returnStruct = createObject("java", "java.util.LinkedHashMap").init()>
NB:虽然可以访问java对象,但是常见的错误是忘记了java是强类型的,与CF不同。如果您不了解它们,通常会subtle nuances that can easily bite you。所以请记住这一点......并确保阅读API。