Yes you are right, the code is not thread safe.
My solution to this problem would be something like this:
Instead of:
Code:
<select id="getSequence" resultMap="result">
select name, nextid from sequence where name = #name#
</select>
<update id="updateSequence">
update sequence set nextid = #nextId# where name = #name#
</update>
I would do:
Code:
<select id="getSequence" resultMap="result">
select name, nextid from sequence where name = #name# for update
</select>
<update id="updateSequence">
update sequence set nextid = (nextid + #cacheSize#) where name = #name#
</update>
A sample code would look like:
Code:
public class SqlMapSequenceDao extends SqlMapClientDaoSupport {
private int cacheSize = 100
private int startId = 0;
private int counter = -1;
private void loadCache(){
Sequence sequence = new Sequence(name, -1);
sequence = (Sequence) getSqlMapClientTemplate().queryForObject("getSequence", sequence);
if (sequence == null) {
throw new DataRetrievalFailureException("Error: A null sequence was returned from the database (could not get next " +
name + " sequence).");
}
startId = sequence.getNextId();
Object parameterObject = new Sequence(name, startId + cacheSize);
getSqlMapClientTemplate().update("updateSequence", parameterObject, 1);
counter = -1;
}
public int getNextId(String name) throws DataAccessException {
counter++;
if(counter > cacheSize){
loadCache();
counter++;
}
return startId + counter;
}
}
The main idea is to provide ids from the in memory cache. The database should be accessed only once in 100 requests.
Hope this code is ok, haven't got time to check it. But overall it should give an idea of what I mean.
Regards, Mircea