У меня странная проблема с моим приложением. Приложение было разработано и протестировано с HSQLDB, и работало нормально. Когда я создал файл WAR и развернул его на сервере, один конкретный фрагмент кода (разумеется, важный для приложения) не удался.
код
def assessment = Assessment.findByPostingAndAssessor(posting, judge)
Ошибка:
Caused by: java.sql.SQLException: No value specified for parameter 2
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1055)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:956)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:926)
at com.mysql.jdbc.PreparedStatement.fillSendPacket(PreparedStatement.java:2214)
at com.mysql.jdbc.PreparedStatement.fillSendPacket(PreparedStatement.java:2138)
at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:1853)
at org.hibernate.jdbc.AbstractBatcher.getResultSet(AbstractBatcher.java:208)
at org.hibernate.loader.Loader.getResultSet(Loader.java:1808)
at org.hibernate.loader.Loader.doQuery(Loader.java:697)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:259)
at org.hibernate.loader.Loader.doList(Loader.java:2228)
Я посмотрел в Google и нашел это довольно старое сообщение в блоге
http://blog.flurdy.com/2008/09/no-value-specified-for-parameter-when.html
, который ссылается на эту проблему и говорит, что она была вызвана плохой версией hibernate. Но это три года; Сейчас я использую Grails 1.3.7 с плагином hibernate 1.3.7. Кроме того, я не мог понять, где найти спецификации maven, которые описываются в блоге, чтобы я мог их редактировать.
И ни одно из моих других приложений не демонстрирует эту проблему. Я попытался использовать искатель, как описано выше, и попытался вручную создать критерий запроса, но оба вывели ту же ошибку Ни одно из значений, переданных методу, не является нулевым.
Мне действительно очень нужно, чтобы это работало КАК МОЖНО СКОРЕЕ, поэтому мне интересно, есть ли у кого-нибудь идеи о том, что попробовать дальше.
Для записи, вы можете увидеть полную трассировку стека здесь: http://grails.1312388.n4.nabble.com/file/n3787337/hibernate-exception.txt
Спасибо
Gene
ИЗД. 02.09.2011:
Вот журнал гибернации / SQL, который приводит к ошибке:
11/09/02 17:56:15 DEBUG hibernate.SQL: select this_.id as id22_0_, this_.version as version22_0_, this_.assessor_id as assessor3_22_0_, this_.comment as comment22_0_, this_.date_created as date5_22_0_, this_.last_updated as last6_22_0_, this_.value as value22_0_ from assessment this_ where this_.id=? and this_.assessor_id=?
11/09/02 17:56:15 TRACE type.LongType: binding '2' to parameter: 1
11/09/02 17:56:15 ERROR util.JDBCExceptionReporter: No value specified for parameter 2
11/09/02 17:56:15 ERROR docusearch.UiController: Could not save assessment
org.hibernate.exception.SQLGrammarException: could not execute query
Далее следует трассировка стека.
ИЗД. 3.09.2011:
Вот участвующие классы:
package com.fxpal.docusearch
import com.sun.org.apache.xalan.internal.xsltc.cmdline.getopt.IllegalArgumentException;
class Assessment {
Posting posting
AssessmentValue value
Searcher assessor
static belongsTo = [posting: Posting, assessor: Searcher]
static indexes = {
posting()
assessor()
}
static constraints = {
posting(nullable: false)
value()
assessor(nullable: true)
}
static judge(Posting posting, Searcher judge, String value) {
if (judge == null)
throw new IllegalArgumentException("missing judge value");
// error occurs here
def assessment = Assessment.findByPostingAndAssessor(posting, judge)
def judgment = AssessmentValue.fromString(value)
if (judgment && !assessment)
assessment = new Assessment( posting: posting, assessor: judge )
if (!judgment && assessment) {
assessment.delete(flush:true)
assessment = null
}
else {
assessment.value = judgment
assessment.save(flush:true)
}
return assessment
}
}
package com.fxpal.docusearch
class Posting {
Document document
int rank
double score
Assessment assessment
static mapping = {
cache true
}
static belongsTo = [document: Document, query: Query]
static constraints = {
document(nullable: false)
rank()
score()
assessment(nullable: true)
}
}
package com.fxpal.docusearch
import com.fxpal.authentication.User
class Searcher Extends User {
String name
String email
String color
static constraints = {
name(blank:false, unique: true, maxSize:255)
email(nullable: true)
color(blank: false)
}
static mapping = {
tablePerHierarchy true
}
public String displayName() {
return name ?: username
}
}
package com.fxpal.authentication
// This is the generic class generated by the Spring Security plugin
class User {
String username
String password = 'n/a'
boolean enabled = true
boolean accountExpired = false
boolean accountLocked = false
boolean passwordExpired = false
static constraints = {
username blank: false, unique: true
password blank: false
}
static mapping = {
password column: '`password`'
}
Set<Role> getAuthorities() {
UserRole.findAllByUser(this).collect { it.role } as Set
}
}
Предполагаете ли вы, что иерархические отношения между Searcher
и User
являются частью проблемы?
Опять же, я должен подчеркнуть, что этот код работает, когда я запускаю его как приложение запуска с базой данных в памяти.
ИЗД. 3.09.2011:
Вот тестовый пример, иллюстрирующий проблему. Работает нормально как grails run-app
(в памяти), но завершается неудачно, когда вы используете 'grails prod run-app` (с базой данных MySQL).
http://grails.1312388.n4.nabble.com/file/n3788449/test.zip
ИЗД. 09.04.2011:
Я задал этот вопрос и группе Grails Nabble, и Даниэль Энрике Алвес Лима выявил потенциальную проблему со схемой моего кода. (См. его пост на Набл). Кажется, проблема в том, что я кодировал:
static belongsTo = [posting: Posting, assessor: Searcher]
в моем Assessment
классе, что привело к поведению, описанному выше. Когда я изменил декларацию на
static belongsTo = [assessor: Searcher]
код findBy..()
работал правильно. Я все еще думаю, что в коде скрывается ошибка гибернации (так как пропуск параметров не является хорошим способом сообщения об ошибках :-)), но по крайней мере моя программа теперь сохраняет данные!
Спасибо всем, кто внес свой вклад в решение!