My first guess was right, iBATIS tries to cast primitive arrays to
Object arrays, this is not allowed. Following is a patch that fixes
this, I don't know if this is the best way to fix it. You could apply
this patch and build iBATIS yourself, in any case, please raise a JIRA
issue @ http://issues.apache.org/jira/browse/IBATIS.
ResultLoader.java:
private static Object listToArray(List list, Class type) {
Object array = java.lang.reflect.Array.newInstance(type, list.size());
if (type.isPrimitive()) {
Iterator iter = list.iterator();
int index = 0;
while (iter.hasNext()) {
Array.set(array, index++, iter.next());
}
} else {
array = list.toArray((Object[]) array);
}
return array;
}
Niels
________________________________
From: Jonathan Alvarsson [mailto:[EMAIL PROTECTED]
Sent: dinsdag 11 september 2007 17:26
To: [email protected]
Subject: Re: How to map a list of double?
On 9/11/07, Niels Beekman <[EMAIL PROTECTED]> wrote:
I don't understand how iBATIS thinks you're trying to map to an
array, do you have overloads for the values-property? Try setting some
debug breakpoints in ResultLoader and find out what's going on. It
definitely should be possible to map to a List or array.
Yes I had that. Removed all such things now bu still can't get this to
work.
Here follows the code from my latest attempt using an array: (and at the
end a stack trace) This time I tried to send as much as possible because
it must be possible to get this to work, otherwise I might as well give
up iBatis...
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE sqlMap PUBLIC "-//iBatis.com//iBatis.com//DTD SQL Map 2.0//EN"
"http://www.ibatis.com/dtd/sql-map-2.dtd">
<sqlMap>
<resultMap class="MoleculeDescriptor" id="MoleculeDescriptor">
<result property="id" column="id" />
<result property="name" column="name" />
<result property="values" column="id"
select="MoleculeDescriptor.getValueList" />
</resultMap>
<procedure id="MoleculeDescriptor.insert"
parameterClass="MoleculeDescriptor">
{CALL insertMoleculeDescriptor(#id#, #name#)}
</procedure>
<select id="MoleculeDescriptor.getValueList" resultClass="double"
parameterClass="String">
SELECT
value AS value
FROM
DescriptorValue
WHERE
abstractDescriptor=#value#
ORDER BY
arrayPos
</select>
<select id="MoleculeDescriptor.getAll"
resultMap="MoleculeDescriptor">
SELECT
p.id AS id,
p.name AS name
FROM
AbstractDescriptor a INNER JOIN PCMBaseObject p ON
(a.pcmBaseObject = p.id)
INNER JOIN MoleculeDescriptor m ON
(a.id = m.id)
</select>
<select id="MoleculeDescriptor.getById"
resultMap="MoleculeDescriptor" parameterClass="String">
SELECT
p.id AS id,
p.name AS name
FROM
AbstractDescriptor a INNER JOIN PCMBaseObject p ON (
a.pcmBaseObject = p.id)
INNER JOIN MoleculeDescriptor m ON (
a.id = m.id)
WHERE
p.id = #value#
</select>
</sqlMap>
public abstract class AbstractDescriptor extends PCMBaseObject {
private double[] values;
private DescriptorType descriptorType;
private DescriptorDatasetRow descriptorDataSetRow;
public AbstractDescriptor() {
super();
values = new double[] {0, 0.1};
}
public AbstractDescriptor( String name, DescriptorType
descriptorType, double[] values ) {
super(name);
setValues(values);
this.descriptorType = descriptorType;
}
public AbstractDescriptor( AbstractDescriptor ad ) {
super(ad);
values = ad.values;
descriptorType = ad.getDescriptorType ();
}
public double[] getValues() {
return values;
}
public void setValues(double[] values) {
this.values = values;
}
public boolean hasValuesEqualTo( PCMBaseObject object ) {
if( !super.hasValuesEqualTo(object) ) {
return false;
}
if( !(object instanceof AbstractDescriptor) ) {
return false;
}
if( this.values.length != ( (AbstractDescriptor)object
).getValues().length ) {
return false;
}
AbstractDescriptor other = (AbstractDescriptor)object;
for( int i = 0; i < values.length; i++ ) {
if( values.length != other.getValues()[i] ) {
return false;
}
}
if( !descriptorType.hasValuesEqualTo( other.getDescriptorType ()
) ) {
return false;
}
return true;
}
public DescriptorType getDescriptorType() {
return descriptorType;
}
public void setDescriptorType(DescriptorType descriptorType) {
this.descriptorType = descriptorType;
}
public DescriptorDatasetRow getDescriptorDataSetRow() {
return descriptorDataSetRow;
}
public void setDescriptorDataSetRow(DescriptorDatasetRow
descriptorDataSetRow) {
this.descriptorDataSetRow = descriptorDataSetRow;
if( !descriptorDataSetRow.getDescriptors().contains(this) ) {
descriptorDataSetRow.addDescriptor(this);
}
}
}
public class MoleculeDescriptor extends AbstractDescriptor {
private PCMMolecule molecule;
public MoleculeDescriptor() {
super();
}
public MoleculeDescriptor( String name, double[] values, PCMMolecule
molecule, DescriptorType descriptorType ) {
super(name, descriptorType, values);
this.molecule = molecule;
if( !molecule.getMoleculeDescriptors().contains(this) ) {
molecule.addMoleculeDescriptor(this);
}
}
public MoleculeDescriptor( MoleculeDescriptor md ) {
super( md );
}
public boolean hasValuesEqualTo( PCMBaseObject object ) {
if( !super.hasValuesEqualTo(object) ) {
return false;
}
if( !(object instanceof MoleculeDescriptor) ) {
return false;
}
return true;
}
public PCMMolecule getMolecule() {
return molecule;
}
public void setMolecule(PCMMolecule molecule) {
this.molecule = molecule;
}
}
org.springframework.jdbc.UncategorizedSQLException : SqlMapClient
operation; uncategorized SQLException for SQL []; SQL state [null];
error code [0];
--- The error occurred in mapping/MoleculeDescriptor.xml.
--- The error occurred while applying a result map.
--- Check the MoleculeDescriptor.
--- Check the result mapping for the 'values' property.
--- Cause: java.lang.ClassCastException: [D; nested exception is
com.ibatis.common.jdbc.exception.NestedSQLException:
--- The error occurred in mapping/MoleculeDescriptor.xml.
--- The error occurred while applying a result map.
--- Check the MoleculeDescriptor.
--- Check the result mapping for the 'values' property.
--- Cause: java.lang.ClassCastException: [D
Caused by: com.ibatis.common.jdbc.exception.NestedSQLException:
--- The error occurred in mapping/MoleculeDescriptor.xml.
--- The error occurred while applying a result map.
--- Check the MoleculeDescriptor.
--- Check the result mapping for the 'values' property.
--- Cause: java.lang.ClassCastException: [D
at
com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.executeQuery
WithCallback(GeneralStatement.java:188)
at
com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.executeQuery
ForList(GeneralStatement.java:123)
at
com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.queryForList(SqlMap
ExecutorDelegate.java:615)
at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.queryForList
(SqlMapExecutorDelegate.java:589)
at
com.ibatis.sqlmap.engine.impl.SqlMapSessionImpl.queryForList(SqlMapSessi
onImpl.java :118)
at
org.springframework.orm.ibatis.SqlMapClientTemplate$3.doInSqlMapClient(S
qlMapClientTemplate.java:268)
at
org.springframework.orm.ibatis.SqlMapClientTemplate.execute(SqlMapClient
Template.java:193)
at
org.springframework.orm.ibatis.SqlMapClientTemplate.executeWithListResul
t(SqlMapClientTemplate.java:219)
at
org.springframework.orm.ibatis.SqlMapClientTemplate.queryForList(SqlMapC
lientTemplate.java:266)
at org.springframework.orm.ibatis.SqlMapClientTemplate.queryForList
(SqlMapClientTemplate.java:260)
at net.bioclipse.pcm.dao.GenericDao.getAll(GenericDao.java:38)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke (Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at
org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(
AopUtils.java:296)
at
org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinp
oint(ReflectiveMethodInvocation.java:177)
at
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(Ref
lectiveMethodInvocation.java:144)
at
net.bioclipse.pcm.dao.FetchIntroductionInterceptor.invoke(FetchIntroduct
ionInterceptor.java:22)
at
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed
(ReflectiveMethodInvocation.java:166)
at
org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAo
pProxy.java :204)
at $Proxy0.getAll(Unknown Source)
at
net.bioclipse.pcm.dao.GenericDaoTest.testGetAll(GenericDaoTest.java:59)
at sun.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at junit.framework.TestCase.runTest(TestCase.java:168)
at junit.framework.TestCase.runBare(TestCase.java:134)
at
org.springframework.test.ConditionalTestCase.runBare(ConditionalTestCase
.java:69)
at
org.springframework.test.annotation.AbstractAnnotationAwareTransactional
Tests.access$001 (AbstractAnnotationAwareTransactionalTests.java:47)
at
org.springframework.test.annotation.AbstractAnnotationAwareTransactional
Tests$1.run (AbstractAnnotationAwareTransactionalTests.java:115)
at
org.springframework.test.annotation.AbstractAnnotationAwareTransactional
Tests.runTest (AbstractAnnotationAwareTransactionalTests.java:180)
at
org.springframework.test.annotation.AbstractAnnotationAwareTransactional
Tests.runTestTimed (AbstractAnnotationAwareTransactionalTests.java:153)
at
org.springframework.test.annotation.AbstractAnnotationAwareTransactional
Tests.runBare (AbstractAnnotationAwareTransactionalTests.java:111)
at junit.framework.TestResult$1.protect(TestResult.java:110)
at junit.framework.TestResult.runProtected(TestResult.java:128)
at junit.framework.TestResult.run(TestResult.java:113)
at junit.framework.TestCase.run (TestCase.java:124)
at junit.framework.TestSuite.runTest(TestSuite.java:232)
at junit.framework.TestSuite.run(TestSuite.java:227)
at
org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run
(JUnit3TestReference.java:130)
at
org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.ja
va:38)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTe
stRunner.java:460)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTe
stRunner.java:673)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRun
ner.java:386)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main
(RemoteTestRunner.java:196)
Caused by: java.lang.ClassCastException: [D
at
com.ibatis.sqlmap.engine.mapping.result.loader.ResultLoader.listToArray(
ResultLoader.java:85)
at
com.ibatis.sqlmap.engine.mapping.result.loader.ResultLoader.getResult(Re
sultLoader.java:75)
at
com.ibatis.sqlmap.engine.mapping.result.loader.ResultLoader.loadResult
(ResultLoader.java:59)
at
com.ibatis.sqlmap.engine.mapping.result.BasicResultMap.getNestedSelectMa
ppingValue(BasicResultMap.java :502)
at
com.ibatis.sqlmap.engine.mapping.result.BasicResultMap.getResults(BasicR
esultMap.java:340)
at
com.ibatis.sqlmap.engine.execution.SqlExecutor.handleResults(SqlExecutor
.java:381)
at
com.ibatis.sqlmap.engine.execution.SqlExecutor.handleMultipleResults(Sql
Executor.java:301)
at com.ibatis.sqlmap.engine.execution.SqlExecutor.executeQuery
(SqlExecutor.java:190)
at
com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.sqlExecuteQu
ery(GeneralStatement.java :205)
at
com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.executeQuery
WithCallback(GeneralStatement.java :173)
... 46 more
--
// Jonathan