Sharing a mapper across multiple threads?

221 views
Skip to first unread message

Romain Vernoux

unread,
Jan 11, 2017, 5:58:52 AM1/11/17
to mybatis-user
Hi,

I have been using MyBatis in my Spring project (with mybatis-spring) for quite some time now, and I after reading a lot of exchanges about the issue of multihreading and thread-safety in mybatis(-spring) I still cannot understand what I should really do in this case. 

The following code resides in a Spring service, in which DataVisualizationDao is a mapper configured with an XML file and @Autowired in the service.
For performance reasons, I want that one call to my service runs multiple queries through the same Dao in parallel. I first came up with the following code:

 
@Autowired 
private DataVisualizationDao dataVisualizationDao;
 
public myFunction(List<...> filters) {
// ... More code 
final ExecutorService executor = Executors.newFixedThreadPool(filters.size());
for (int i = 0; i < filters.size(); i++) {
int index = i;
executor.execute(() -> {
aSynchronizedMap.put(index, dataVisualizationDao.aQuery(index));
});
}
// ... More code 

 
Very randomly though, I get the following error:

Exception in thread "pool-2-thread-1" org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.binding.BindingException: Parameter 'null' not found. Available parameters are [filters, aggregationConfig, param3, lessorId, param1, param2]
at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:75)
at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:371)
at com.sun.proxy.$Proxy54.selectList(Unknown Source)
at org.mybatis.spring.SqlSessionTemplate.selectList(SqlSessionTemplate.java:198)
at org.apache.ibatis.binding.MapperMethod.executeForMany(MapperMethod.java:114)
at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:58)
at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:43)

The fact that it occurs very randomly points me towards concurrency issues. I've also had random ArrayIndexOutOfBoundsExceptions and NPEs there before but I did not save the Stacktrace. I believe they are the symptoms of the same core issue.

I understand that since DataVisualizationDao is a Spring Bean, it is a singleton in the calling thread (i.e., the thread handling the http request and calling my service). But it looks like the dao implementation itself is not thread-safe. What should I do then?
I've read about something like this, using the fact that the SqlSessionFactory is thread-safe:


@Autowired
private SqlSessionFactory sqlSessionFactory;

public myFunction(List<...> filters) {
// ... More code
final ExecutorService executor = Executors.newFixedThreadPool(filters.size());
for (int i = 0; i < filters.size(); i++) {
int index = i;
executor.execute(() -> { 
SqlSession session = sqlSessionFactory.openSession();
try {
DataVisualizationDao dataVisualizationDao = session.getMapper(DataVisualizationDao.class);
aSynchronizedHashmap.put(index, dataVisualizationDao.aQuery(index));
} finally {
session.close();
}
});
// ... More code
}

But after debugging this I still see that many objects inside the different dao instances are shared. Since the error is super-hard to reproduce to begin with, I can't know for sure if this solution fixes my issue or not.
Reply all
Reply to author
Forward
0 new messages