/*
* @(#)ShardImpl.java 2012-8-1 下午10:00:00
*
* Copyright (c) 2011-2012 Makersoft.org all rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
*
*/
package org.makersoft.shards;
import static org.apache.ibatis.reflection.ExceptionUtil.unwrapThrowable;
import static org.mybatis.spring.SqlSessionUtils.closeSqlSession;
import static org.mybatis.spring.SqlSessionUtils.isSqlSessionTransactional;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Collection;
import java.util.Set;
import org.apache.ibatis.exceptions.PersistenceException;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.MyBatisExceptionTranslator;
import org.mybatis.spring.SqlSessionUtils;
import org.springframework.dao.support.PersistenceExceptionTranslator;
/**
*
*/
public class ShardImpl implements Shard {
private final SqlSessionFactory sqlSessionFactory;
private final PersistenceExceptionTranslator exceptionTranslator;
private final SqlSession sqlSessionProxy;
private final Set<ShardId> shardIds;
public final ExecutorType executorType = ExecutorType.SIMPLE;
public ShardImpl(Set<ShardId> shardIds, SqlSessionFactory sqlSessionFactory){
this.shardIds = shardIds;
this.sqlSessionFactory = sqlSessionFactory;
this.exceptionTranslator = new MyBatisExceptionTranslator(
sqlSessionFactory.getConfiguration().getEnvironment().getDataSource(), true);
this.sqlSessionProxy = (SqlSession) Proxy.newProxyInstance(
SqlSessionFactory.class.getClassLoader(),
new Class[] { SqlSession.class },
new SqlSessionInterceptor());
}
private Configuration getConfiguration(){
return sqlSessionFactory.getConfiguration();
}
@Override
public SqlSessionFactory getSqlSessionFactory(){
return sqlSessionFactory;
}
@Override
public SqlSession getSqlSession() {
return sqlSessionProxy;
}
@Override
public Set<ShardId> getShardIds() {
return shardIds;
}
@Override
public SqlSession establishSqlSession() {
// if(sqlSession == null){
// sqlSession = sqlSessionFactory.openSession();
// }
return sqlSessionProxy;
}
@Override
public Collection<String> getMappedStatementNames() {
return getConfiguration().getMappedStatementNames();
}
@Override
public boolean hasMapper(Class<?> type) {
return getConfiguration().hasMapper(type);
}
private class SqlSessionInterceptor implements InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
final SqlSession sqlSession = SqlSessionUtils.getSqlSession(
ShardImpl.this.sqlSessionFactory,
ShardImpl.this.executorType ,
ShardImpl.this.exceptionTranslator);
try {
Object result = method.invoke(sqlSession, args);
if (!isSqlSessionTransactional(sqlSession, ShardImpl.this.sqlSessionFactory)) {
// force commit even on non-dirty sessions because some databases require
// a commit/rollback before calling close()
sqlSession.commit(true);
}
return result;
} catch (Throwable t) {
Throwable unwrapped = unwrapThrowable(t);
if (ShardImpl.this.exceptionTranslator != null && unwrapped instanceof PersistenceException) {
Throwable translated = ShardImpl.this.exceptionTranslator.translateExceptionIfPossible((PersistenceException) unwrapped);
if (translated != null) {
unwrapped = translated;
}
}
throw unwrapped;
} finally {
closeSqlSession(sqlSession, ShardImpl.this.sqlSessionFactory);
}
}
}
}