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]


Reply via email to