So I'm having trouble understanding why a resultSet from an executed query will not continue to advance when there's clearly more entries to iterate over. I have a table called all_projects, and when I run this query:
SELECT project_title, created_date, isActive FROM all_projects WHERE project_lead='myUser' ORDER BY created_date DESC;
in my PSQL shell, this is the result I get:
The column data types are: String, Timestamp, and Boolean.
I'm attempting to get each row, create an Array[String] from it, to create, ultimately, a list of an array of strings ( List[Array[String]]
)
When I iterate over this with resultSet.next(), it is able to retrieve the first two values, but then when I call next after acquiring the first timestamp value, it fails and returns false.
Below is my code - riddled with a lot of println debug statements to see what happens, stack/and print trace will be at the bottom.
def getAll(userName: String, db: Database): List[Array[String]] = {
val tablesQuery = s"SELECT project_title, created_date, isActive FROM all_projects WHERE project_lead=? ORDER BY created_date DESC;"
var returnResult = new ListBuffer[Array[String]]
db.withConnection { conn =>
val ps = conn.prepareStatement(tablesQuery)
ps.setString(1, userName)
val qryResult = ps.executeQuery()
val columnCount = qryResult.getMetaData.getColumnCount
println("RETRIEVED THIS MANY COLUMNS: " + columnCount)
while (qryResult.next()) {
println("Achieved next in while loop >>>>>>>>>>>")
val row = new Array[String](columnCount)
for (i <- 0 to columnCount - 1) {
println(s"Inserting into Array($i) from the column index(${i + 1})")
if (i < 2) {
println("Tried to get string: ");
row(i) = qryResult.getString(i + 1)
} else { // note I also just tried to keep it all as .getString()
println("Tried to get boolean: ");
row(i) = qryResult.getBoolean(i+1).toString
} // retrieve by column index SQL columns start at 1
println("Row before we move on: " + row.mkString(", "))
if (i <= columnCount - 2) {
println("Called next? -> " + qryResult.next())
}
}
returnResult += row
}
}
returnResult.toList
}
And here is the resulting print stack, which should have been fine, but as you can see, returns false
when attempting next()
when the cursor is on the first timestamp value.
THIS MANY COLUMNS: 3
Achieved next in while loop >>>>>>>>>>>
Inserting into Array(0) from the column index(1)
Tried to get string:
Row before we move on: Wild Elephants of Mexico, null, null
Called next? -> true
Inserting into Array(1) from the column index(2)
Tried to get string:
Row before we move on: Wild Elephants of Mexico, 2017-08-05 11:00:44.078232, null
Called next? -> false
Inserting into Array(2) from the column index(3)
Tried to get boolean:
[error] o.j.ResultSetLogger - java.sql.ResultSet.getBoolean:
throws exception: org.postgresql.util.PSQLException: ResultSet not positioned properly, perhaps you need to call next.
org.postgresql.util.PSQLException: ResultSet not positioned properly, perhaps you need to call next.
What is happening here?
答案 0 :(得分:3)
You are calling qryResult.next()
within what you mean to be the handling of a single row, breaking everything. (Boy are you making your life much too difficult.)
A ResultSet
represents a query result as a movable pointer to a single row of the query result. You handle rows one at a time, and then call next()
only when you have fully completed handling of that row.
Let's make things much much simpler. (I'm just writing this out in a web page, don't have time to check or compile it, so please excuse my boo-boos.)
def handleRow( qryResult : ResultSet, columnCount : Int ) : Array[String] = {
(1 to columnCount).map( i => qryResult.getString(i) ).toArray
}
def getAll(userName: String, db: Database): List[Array[String]] = {
val tablesQuery = s"SELECT project_title, created_date, isActive FROM all_projects WHERE project_lead=? ORDER BY created_date DESC;"
db.withConnection { conn =>
val ps = conn.prepareStatement(tablesQuery)
ps.setString(1, userName)
val qryResult = ps.executeQuery()
val columnCount = qryResult.getMetaData.getColumnCount
println("RETRIEVED THIS MANY COLUMNS: " + columnCount)
var buffer = new ListBuffer[Array[String]]
while (qryResult.next()) {
buffer += handleRow( qryResult, columnCount )
}
buffer.toList
}
}