Thank you Brandon for your replies on this thread.
I did end up trying to make a simpler case. I started to use ResultMaps
to populate the complex type and can still replicate the problem. Since
I believe this is a true iBATIS bug I sent a simplified description and
test case to the ibatis dev mailing list - see the thread entitled
'Caught exception: 'Duplicate prepared statement found. This is likely
a bug.''
Regarding the use of 'Statement', since I am using stored
procedures/functions exclusively I did not see any advantage of
'procedure' over statement. In particular, it bothered me to use a
'procedure' element for stored functions and then need to use a SELECT
in calling the function. While writing this, I just tried changing
'statement' to 'procedure' and my very first call threw a null pointer
exception:
Changing this:
<statement id="getResearcherByUsername" parameterClass="String"
resultClass="Researcher" cacheModel="bigCache">
CALL getResearcherByUsername(#pUserName:VARCHAR#)
</statement>
to:
<procedure id="getResearcherByUsername" parameterClass="String"
resultClass="Researcher" cacheModel="bigCache">
CALL getResearcherByUsername(#pUserName:VARCHAR#)
</procedure>
resulted in this:
2006-11-16 11:18:24,350 INFO : iBATIS SqlMap for db 'GeneDataset'
initialized
2006-11-16 11:18:24,351 DEBUG: queryForObject getResearcherByUsername
passing: PeterVermont
com.ibatis.common.jdbc.exception.NestedSQLException:
--- The error occurred in
org/epistasis/db/geneDataset/GeneDataset.xml.
--- The error occurred while executing query procedure.
--- Check the CALL getResearcherByUsername(?).
--- Check the SQL Statement (preparation failed).
--- Cause: java.lang.NullPointerException
Caused by: java.lang.NullPointerException
at
com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.executeQueryWithCallback(GeneralStatement.java:188)
at
com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.executeQueryForObject(GeneralStatement.java:104)
at
com.ibatis.sqlmap.engine.mapping.statement.CachingStatement.executeQueryForObject(CachingStatement.java:79)
2006-11-16 11:18:24,690 ERROR: Static initializer Caught an exception:
com.ibatis.common.jdbc.exception.RuntimeSQLException:
com.ibatis.common.jdbc.exception.NestedSQLException:
--- The error occurred in
org/epistasis/db/geneDataset/GeneDataset.xml.
--- The error occurred while executing query procedure.
--- Check the CALL getResearcherByUsername(?).
--- Check the SQL Statement (preparation failed).
--- Cause: java.lang.NullPointerException
Caused by: java.lang.NullPointerException
at
com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.queryForObject(SqlMapExecutorDelegate.java:566)
at
com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.queryForObject(SqlMapExecutorDelegate.java:541)
at
com.ibatis.sqlmap.engine.impl.SqlMapSessionImpl.queryForObject(SqlMapSessionImpl.java:106)
at
com.ibatis.sqlmap.engine.impl.SqlMapClientImpl.queryForObject(SqlMapClientImpl.java:83)
at
org.epistasis.db.SqlMapClientWrapper.queryForObject(SqlMapClientWrapper.java:22)
at
org.epistasis.db.geneDataset.GeneDatasetDbAccess.getResearcherByUsername(GeneDatasetDbAccess.java:93)
at
org.epistasis.db.geneDataset.GeneDatasetDbAccess.login(GeneDatasetDbAccess.java:47)
at
org.epistasis.eva.gui.JDialogLogin.btnLoginActionPerformed(JDialogLogin.java:125)
at
org.epistasis.eva.gui.JDialogLogin.access$100(JDialogLogin.java:21)
at
org.epistasis.eva.gui.JDialogLogin$2.actionPerformed(JDialogLogin.java:65)
at
javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1849)
at
javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2169)
at
javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:420)
at
javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:258)
at
javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:234)
at java.awt.Component.processMouseEvent(Component.java:5488)
at
javax.swing.JComponent.processMouseEvent(JComponent.java:3126)
at java.awt.Component.processEvent(Component.java:5253)
at java.awt.Container.processEvent(Container.java:1966)
at java.awt.Component.dispatchEventImpl(Component.java:3955)
at java.awt.Container.dispatchEventImpl(Container.java:2024)
at java.awt.Component.dispatchEvent(Component.java:3803)
at
java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4212)
at
java.awt.LightweightDispatcher.processMouseEvent(Container.java:3892)
at
java.awt.LightweightDispatcher.dispatchEvent(Container.java:3822)
at java.awt.Container.dispatchEventImpl(Container.java:2010)
at java.awt.Window.dispatchEventImpl(Window.java:1774)
at java.awt.Component.dispatchEvent(Component.java:3803)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:463)
at
java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:242)
at
java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:163)
at
java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:153)
at java.awt.Dialog$1.run(Dialog.java:517)
at java.awt.Dialog$2.run(Dialog.java:545)
at java.security.AccessController.doPrivileged(Native Method)
at java.awt.Dialog.show(Dialog.java:543)
at java.awt.Component.show(Component.java:1300)
at java.awt.Component.setVisible(Component.java:1253)
at
org.epistasis.eva.gui.JDialogLogin.Login(JDialogLogin.java:157)
at org.epistasis.eva.gui.FrameMain$1.run(FrameMain.java:502)
at
java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:461)
at
java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:242)
at
java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:163)
at
java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:157)
at
java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:149)
at
java.awt.EventDispatchThread.run(EventDispatchThread.java:110)
Caused by: java.lang.NullPointerException
at
com.mysql.jdbc.StringUtils.indexOfIgnoreCaseRespectQuotes(StringUtils.java:959)
at
com.mysql.jdbc.DatabaseMetaData.getCallStmtParameterTypes(DatabaseMetaData.java:1296)
at
com.mysql.jdbc.DatabaseMetaData.getProcedureColumns(DatabaseMetaData.java:3670)
at
com.mysql.jdbc.CallableStatement.determineParameterTypes(CallableStatement.java:702)
at
com.mysql.jdbc.CallableStatement.<init>(CallableStatement.java:513)
at
com.mysql.jdbc.Connection.parseCallableStatement(Connection.java:4422)
at com.mysql.jdbc.Connection.prepareCall(Connection.java:4496)
at com.mysql.jdbc.Connection.prepareCall(Connection.java:4470)
at
org.apache.commons.dbcp.DelegatingConnection.prepareCall(DelegatingConnection.java:212)
at
org.apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper.prepareCall(PoolingDataSource.java:268)
at
com.ibatis.sqlmap.engine.execution.SqlExecutor.prepareCall(SqlExecutor.java:498)
at
com.ibatis.sqlmap.engine.execution.SqlExecutor.executeQueryProcedure(SqlExecutor.java:260)
at
com.ibatis.sqlmap.engine.mapping.statement.ProcedureStatement.sqlExecuteQuery(ProcedureStatement.java:34)
at
com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.executeQueryWithCallback(GeneralStatement.java:173)
... 49 more
Brandon Goodin wrote:
>From what i can see of your code you are trying to use iBATIS in
more of an Active Record fashion. With iBATIS it is not a good idea to
make database calls from within your domain beans. As a general
practice, it is best to operate on your domain beans externally either
by providing information to the bean at instantiation(not supported in
iBATIS) or via a getter/setter (supported). An enhanced route to go for
using the setter is to setup a resultMap that can populate a complex
type. This would essentially be using the setter. Since you expose your
setter and getter. I would recommend that you use a result map.
As a side note I noticed you were using <statement> for all of
your mapped statements... there are others available as well
<procedure>, <select>, <insert>, <update>,
<delete>. There are variations between them that provide more
focused control over the type of database call and return type.
Hope that helps,
Brandon Goodin
On 11/15/06, Peter Andrews <[EMAIL PROTECTED]>
wrote:
I am sorry but I don't have the time to distill everything to
a nice
example. My guess is that it easy to replicate by following my
essential (possibly poor) technique which is that the setter for one of
my resultClass properties makes another call to the db via iBATIS (see
the setGeneKey method in GeneExperimentResult.java).
As I read more about iBATIS, I realize the more conventional way to
accomplish what I want is to use a resultMap with Complex Properties
such that a returned foreignKey to another class retrieves that class.
I did not do so because I think it is more complicated, particularly
given that I am not using any resultMaps since my column names and bean
names match exactly.
Brandon Goodin wrote:
Please post your code involved in producing this. Post
sqlmap config, dao java code, and bean java code.
Brandon
On 11/14/06, Peter Andrews <
[EMAIL PROTECTED]> wrote:
I
am sorry if this has been discussed previously -- the mail archives
seem to be currently unavailable (get network connection error).
I am getting an error. The error message is different between 2.2.0 and
the subversion latest. The error in the subject line is from the
subversion code. In the 2.2.0 I get:
com.mysql.jdbc.exceptions.MySQLSyntaxErrorException: Result consisted of
more than one row
When the message says 'This is likely a bug' does it mean a bug in
iBATIS or a bug in my code? I think it means iBATIS.
At the bottom of this email is a partial stack trace (the full trace
goes on for a very long time repeating itself and ends with '...30
more').
I think the issue is that one of my calls into iBATIS can cause
additional calls to occur before the first one ends. This is because
some of my setter functions also make calls to the db.
The iBATIS code that is throwing the exception is in SessionScope.java:
public void putPreparedStatement(String sql, PreparedStatement ps) {
if (!isInBatch()) {
if (hasPreparedStatementFor(sql))
throw new SqlMapException("Duplicate prepared statement found.
This is likely a bug.");
preparedStatements.put(sql, ps);
}
}
Changing the iBATIS code to:
if (!hasPreparedStatementFor(sql))
preparedStatements.put(sql, ps);
appears to fix the problem. I am an iBATIS novice user so is likely not
a correct fix (if the problem is even iBATIS').
Here is the stack trace:
run-single:
DEBUG: iBATIS SqlMap for db 'GeneDataset' initialized
DEBUG: queryForObject 'getResearcherByUsername' passing: PeterVermont
DEBUG: queryForObject 'getResearcherByUsername' returning:
org.epistasis.db.geneExperiment.Researcher[id=1]
DEBUG: queryForList 'getGeneExperimentResultsByDatasetExperimentId'
passing: 1 <==*********************NOTE: Still in process when
when
following calls start
DEBUG: queryForObject 'getGeneKeyById' passing: 1
DEBUG: queryForObject 'getGeneKeyById' returning:
org.epistasis.db.geneExperiment.GeneKey[id=1]
DEBUG: queryForObject 'getGeneKeyById' passing:
2
<==*********************NOTE: second call to getGeneKeyById since
'getGeneExperimentResultsByDatasetExperimentId' started
com.ibatis.common.jdbc.exception.NestedSQLException:
--- The error occurred in org/epistasis/db/geneDataset/GeneDataset.xml.
--- The error occurred while executing query.
--- Check the CALL getGeneKeyById(?) .
--- Check the SQL Statement (preparation failed).
--- Cause: com.ibatis.sqlmap.client.SqlMapException: Duplicate prepared
statement found. This is likely a bug.
Caused by: com.ibatis.sqlmap.client.SqlMapException: Duplicate prepared
statement found. This is likely a bug.
at
com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.executeQueryWithCallback
(GeneralStatement.java:188)
at
com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.executeQueryForObject(GeneralStatement.java:104)
at
com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.queryForObject
(SqlMapExecutorDelegate.java:566)
at
com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.queryForObject(SqlMapExecutorDelegate.java:541)
at
com.ibatis.sqlmap.engine.impl.SqlMapSessionImpl.queryForObject
(SqlMapSessionImpl.java:106)
at
com.ibatis.sqlmap.engine.impl.SqlMapClientImpl.queryForObject(SqlMapClientImpl.java:83)
at
org.epistasis.db.SqlMapClientWrapper.queryForObject(SqlMapClientWrapper.java
:21)
at
org.epistasis.db.geneDataset.GeneDatasetDbAccess.getGeneKeyById(GeneDatasetDbAccess.java:94)
at
org.epistasis.db.geneDataset.GeneKey.getGeneKeyById(GeneKey.java:49)
at
org.epistasis.db.geneDataset.GeneExperimentResult.setGeneKeyId
(GeneExperimentResult.java:110)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke
(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at
com.ibatis.sqlmap.engine.accessplan.PropertyAccessPlan.setProperties(PropertyAccessPlan.java:46)
at
com.ibatis.sqlmap.engine.exchange.JavaBeanDataExchange.setData(JavaBeanDataExchange.java:115)
at
com.ibatis.sqlmap.engine.mapping.result.BasicResultMap.setResultObjectValues(BasicResultMap.java:373)
at
com.ibatis.sqlmap.engine.mapping.statement.RowHandlerCallback.handleResultObject(RowHandlerCallback.java:64)
ERROR: Caught an exception
at
com.ibatis.sqlmap.engine.execution.SqlExecutor.handleResults(
SqlExecutor.java:377)
at
com.ibatis.sqlmap.engine.execution.SqlExecutor.handleMultipleResults(SqlExecutor.java:296)
at
com.ibatis.sqlmap.engine.execution.SqlExecutor.executeQuery(SqlExecutor.java
:187)
com.ibatis.common.jdbc.exception.RuntimeSQLException:
com.ibatis.common.jdbc.exception.NestedSQLException:
--- The error occurred in org/epistasis/db/geneDataset/GeneDataset.xml.
--- The error occurred while applying a result map.
--- Check the
getGeneExperimentResultsByDatasetExperimentId-AutoResultMap.
--- The error happened while setting a property on the result object.
--- Cause: java.lang.RuntimeException: Error setting property
'setGeneKeyId' of
'org.epistasis.db.geneExperiment.GeneExperimentResult[id=2]'. Cause:
com.ibatis.common.jdbc.exception.RuntimeSQLException:
com.ibatis.common.jdbc.exception.NestedSQLException:
--- The error occurred in org/epistasis/db/geneDataset/GeneDataset.xml.
--- The error occurred while executing query.
--- Check the CALL getGeneKeyById(?) .
--- Check the SQL Statement (preparation failed).
--- Cause: com.ibatis.sqlmap.client.SqlMapException: Duplicate prepared
statement found. This is likely a bug.
Caused by: com.ibatis.sqlmap.client.SqlMapException: Duplicate prepared
statement found. This is likely a bug.
Caused by: java.lang.RuntimeException: Error setting property
'setGeneKeyId' of
'org.epistasis.db.geneExperiment.GeneExperimentResult[id=2]'. Cause:
com.ibatis.common.jdbc.exception.RuntimeSQLException:
com.ibatis.common.jdbc.exception.NestedSQLException:
--- The error occurred in org/epistasis/db/geneDataset/GeneDataset.xml.
--- The error occurred while executing query.
at
com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.sqlExecuteQuery(GeneralStatement.java:205)
--- Check the CALL getGeneKeyById(?) .
at
com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.executeQueryWithCallback(GeneralStatement.java:173)
--- Check the SQL Statement (preparation failed).
at
com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.executeQueryForList
(GeneralStatement.java:123)
--- Cause: com.ibatis.sqlmap.client.SqlMapException: Duplicate prepared
statement found. This is likely a bug.
at
com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.queryForList
(SqlMapExecutorDelegate.java:615)
Caused by: com.ibatis.sqlmap.client.SqlMapException: Duplicate prepared
statement found. This is likely a bug.
at
com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.queryForList
(SqlMapExecutorDelegate.java:589)
at
com.ibatis.sqlmap.engine.impl.SqlMapSessionImpl.queryForList(SqlMapSessionImpl.java:118)
at
org.epistasis.db.SqlMapClientWrapper.queryForList(SqlMapClientWrapper.java
:50)
at
com.ibatis.sqlmap.engine.impl.SqlMapClientImpl.queryForList(SqlMapClientImpl.java:95)
at
org.epistasis.db.geneDataset.GeneDatasetDbAccess.getGeneExperimentResultsByDatasetExperimentId(GeneDatasetDbAccess.java
:90)
at
org.epistasis.db.SqlMapClientWrapper.queryForList(SqlMapClientWrapper.java:45)
at
org.epistasis.db.geneDataset.GeneDatasetDbAccess.main(GeneDatasetDbAccess.java:167)
at
org.epistasis.db.geneDataset.GeneDatasetDbAccess.getGeneExperimentResultsByDatasetExperimentId
(GeneDatasetDbAccess.java:90)
Caused by: com.ibatis.common.jdbc.exception.NestedSQLException:
at
org.epistasis.db.geneDataset.GeneDatasetDbAccess.main(GeneDatasetDbAccess.java:167)
--- The error occurred in org/epistasis/db/geneDataset/GeneDataset.xml.
Caused by: com.ibatis.sqlmap.client.SqlMapException: Duplicate prepared
statement found. This is likely a bug.
--- The error occurred while applying a result map.
at
com.ibatis.sqlmap.engine.scope.SessionScope.putPreparedStatement
(SessionScope.java:247)
--- Check the
getGeneExperimentResultsByDatasetExperimentId-AutoResultMap.
at
com.ibatis.sqlmap.engine.execution.SqlExecutor.prepareStatement(SqlExecutor.java:488)
--- The error happened while setting a property on the result object.
at
com.ibatis.sqlmap.engine.execution.SqlExecutor.executeQuery(SqlExecutor.java:173)
--- Cause: java.lang.RuntimeException: Error setting property
'setGeneKeyId' of
'org.epistasis.db.geneExperiment.GeneExperimentResult
[id=2]'. Cause:
com.ibatis.common.jdbc.exception.RuntimeSQLException:
com.ibatis.common.jdbc.exception.NestedSQLException:
at
com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.sqlExecuteQuery
(GeneralStatement.java:205)
--- The error occurred in org/epistasis/db/geneDataset/GeneDataset.xml.
at
com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.executeQueryWithCallback(GeneralStatement.java
:173)
--- The error occurred while executing query.
... 30 more
--
Peter Andrews
Software Engineer
Dartmouth Medical School
Computational Genetics
Rubin 707
(603) 653-3598
[EMAIL PROTECTED]
--
Peter Andrews
Software Engineer
Dartmouth Medical School
Computational Genetics
Rubin 707
(603) 653-3598
[EMAIL PROTECTED]
--
Peter Andrews
Software Engineer
Dartmouth Medical School
Computational Genetics
Rubin 707
(603) 653-3598
[EMAIL PROTECTED]
|