Many thanks for the reply, Clinton - but sadly this doesn't seem to fix the
problem. My understanding was that readonly need only be set to "false" if a
thread is likely to change the contents of the returned object - this is not
the case in my example application (indeed, the returned object is a String).
I've appended my code and iBATIS configuration files below - I'd appreciate it
if you could tell me if I'm doing anything obviously wrong. My understanding
was that a SqlMapClient object could safely be used from multiple threads (and
that it would handle the caching appropriately).
Thanks,
Alistair.
IBatisTest.java:
------------------------------------------------------------
package test;
public class IBatisTest implements Runnable {
private SqlMapClient sql;
public IBatisTest() throws Exception {
// create the SQL map
Reader reader = Resources.getResourceAsReader("SqlMapConfig.xml");
this.sql = SqlMapClientBuilder.buildSqlMapClient(reader);
}
public void runTest() throws Exception {
this.sql.startTransaction();
String value = (String)this.sql.queryForObject("db.getValue");
System.out.println("Value is " + value); // "1"
this.sql.update("db.updateValue", "2");
value = (String)this.sql.queryForObject("db.getValue");
System.out.println("Value is " + value); // "2"
// start the other thread
new Thread(this).start();
// wait for a bit
Thread.sleep(2000);
// roll back the transaction
this.sql.endTransaction();
value = (String)this.sql.queryForObject("db.getValue");
System.out.println("Value is " + value); // "2" (expecting "1")
}
// second thread
public void run() {
try {
String value = (String)this.sql.queryForObject("db.getValue");
System.out.println(" Value is " + value); // "2" (expecting "1")
} catch (Exception x) {
throw new RuntimeException(x);
}
}
public static void main(String[] args) throws Exception {
new IBatisTest().runTest();
}
}
------------------------------------------------------------
SqlMapConfig.xml:
------------------------------------------------------------
<?xml version="1.0" encoding="windows-1252" ?>
<!DOCTYPE sqlMapConfig
PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN"
"sql-map-config-2.dtd">
<sqlMapConfig>
<settings
useStatementNamespaces="true"
lazyLoadingEnabled="true"
enhancementEnabled="true"
statementCachingEnabled="false" />
<transactionManager type="JDBC">
<dataSource type="SIMPLE">
<property name="JDBC.Driver" value="oracle.jdbc.OracleDriver"/>
<property name="JDBC.ConnectionURL" value="..."/>
<property name="JDBC.Username" value="..."/>
<property name="JDBC.Password" value="..."/>
</dataSource>
</transactionManager>
<!-- at least one SQL Map is required for this to be a
valid configuration file -->
<sqlMap resource="SqlMap.xml"/>
</sqlMapConfig>
------------------------------------------------------------
and SqlMap.xml:
------------------------------------------------------------
<?xml version="1.0" encoding="windows-1252" ?>
<!DOCTYPE sqlMap
PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
"sql-map-2.dtd">
<sqlMap namespace="db">
<cacheModel id="cache" type="FIFO" readOnly="false" serialize="true">
<flushOnExecute statement="db.updateValue"/>
<property name="size" value="10"/>
</cacheModel>
<insert id="updateValue" parameterClass="String">
update VALUES set VALUE=#value# where ID=1
</insert>
<select id="getValue" resultClass="String" cacheModel="cache">
select VALUE from VALUES where ID=1
</select>
</sqlMap>
------------------------------------------------------------
-----Original Message-----
From: Clinton Begin [mailto:[email protected]]
Sent: 12 January 2009 15:23
To: [email protected]
Subject: Re: iBATIS caching / transaction isolation question
The uncommitted data would be seen by thread B as you expect, *if* the cache is
configured as read-only.
To stop this problem, set the cache to read/write and serializable.
Sorry for the confusing configuration here.
Clinton
On 1/12/09, Young, Alistair <[email protected]> wrote:
> Apologies for following up my own post...
>
> I carried out a simple test and found that transaction isolation is
> not maintained. Also, the cache is not flushed in the event of a
> transaction being rolled back.
>
> The sequence of events was:
>
> Thread A: start transaction
> Thread A: select value ("1" is returned) Thread A: update value to "2"
> Thread A: select value ("2" is returned)
>
> Thread B: select value ("2" is returned - not "1")
>
> Thread A: rollback transaction
> Thread A: select value ("2" is returned - not "1")
>
> Is this the expected behaviour?
>
> If not, what might I be doing wrong? If so, how do people deal with
> this behaviour?
>
> Thanks for any advice,
>
>
> Alistair.
>
> ________________________________
>
> From: Young, Alistair
> Sent: 12 January 2009 10:54
> To: [email protected]
> Subject: iBATIS caching / transaction isolation question
>
>
> Hello all,
>
> I wonder if somebody could clarify for me how iBATIS caching works
> with regards to transaction isolation.
>
> Suppose I have a cache set up with is used when a "selectAllItems"
> statement is invoked, and flushed when an "updateItem" statement is
> invoked.
>
> Suppose then that thread A starts a transaction, invokes updateItem
> and then selectAllItems. Then, before thread A completes the
> transaction, thread B invokes selectAllItems.
>
> Is transaction isolation maintained, or does thread B end up seeing
> the
> (uncommitted) data that thread A has updated?
>
> I should add that I haven't actually tried this yet - but I'd like to
> know what the expected behaviour is before getting stuck in.
>
> In our particular use case, we're making use of a custom
> TransactionConfig (which is essentially the same as "EXTERNAL" but
> handles connection creation slightly differently). And we're not
> making any explicit calls to the iBATIS transaction methods.
>
> Many thanks!
>
>
> Alistair.
>
>
>
>
> Please help Logica to respect the environment by not printing this
> email / Merci d'aider Logica à préserver l'environnement en évitant
> d'imprimer ce mail / Bitte drucken Sie diese Nachricht nicht aus und
> helfen Sie so Logica dabei die Umwelt zu schuetzen / Por favor ajude
> a Logica a respeitar o ambiente não imprimindo este correio electrónico.
>
>
>
> This e-mail and any attachment is for authorised use by the intended
> recipient(s) only. It may contain proprietary material, confidential
> information and/or be subject to legal privilege. It should not be
> copied, disclosed to, retained or used by, any other party. If you are
> not an intended recipient then please promptly delete this e-mail and
> any attachment and all copies and inform the sender. Thank you.
>
>
--
Sent from my mobile device
Please help Logica to respect the environment by not printing this email /
Merci d'aider Logica à préserver l'environnement en évitant d'imprimer ce mail
/ Bitte drucken Sie diese Nachricht nicht aus und helfen Sie so Logica dabei
die Umwelt zu schuetzen / Por favor ajude a Logica a respeitar o ambiente não
imprimindo este correio electrónico.
This e-mail and any attachment is for authorised use by the intended
recipient(s) only. It may contain proprietary material, confidential
information and/or be subject to legal privilege. It should not be copied,
disclosed to, retained or used by, any other party. If you are not an intended
recipient then please promptly delete this e-mail and any attachment and all
copies and inform the sender. Thank you.