Java tutorial
/* * Copyright 2009 zaichu xiao * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package zcu.xutil.orm; import java.io.InputStream; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.sql.Connection; import java.util.List; import java.util.Map; import javax.sql.DataSource; import org.apache.ibatis.builder.xml.XMLConfigBuilder; import org.apache.ibatis.exceptions.ExceptionFactory; import org.apache.ibatis.executor.BatchResult; import org.apache.ibatis.executor.ErrorContext; import org.apache.ibatis.io.Resources; import org.apache.ibatis.mapping.Environment; import org.apache.ibatis.session.Configuration; import org.apache.ibatis.session.ExecutorType; import org.apache.ibatis.session.ResultHandler; import org.apache.ibatis.session.RowBounds; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.apache.ibatis.transaction.managed.ManagedTransactionFactory; import zcu.xutil.txm.MResource; import zcu.xutil.txm.MResourceFactory; import zcu.xutil.txm.SmartDataSource; import zcu.xutil.txm.TxManager; import static zcu.xutil.Objutil.*; public class MyBatisSession implements SqlSession { public static Configuration parse(String configFile) { InputStream in = null; try { return new XMLConfigBuilder(in = Resources.getResourceAsStream(configFile)).parse(); } catch (Exception e) { throw ExceptionFactory.wrapException("parse MyBatis Configuration error.", e); } finally { closeQuietly(in); ErrorContext.instance().reset(); } } private final SqlSession delegate; private final ResFactory resFactory; public MyBatisSession(DataSource dataSource, String configFile) { this(dataSource, configFile, null); } public MyBatisSession(DataSource dataSource, String configFile, ExecutorType executorType) { this(dataSource, parse(configFile), executorType); } public MyBatisSession(DataSource dataSource, Configuration configuration, ExecutorType executorType) { delegate = (SqlSession) newProxy(SqlSession.class, resFactory = new ResFactory(dataSource, configuration, executorType)); } private SqlSession getDelegate() { try { SqlSession s = (SqlSession) TxManager.getTxManager().getConnection(resFactory); return s != null ? s : delegate; } catch (Exception e) { throw rethrow(e); } } @Override public final void clearCache() { getDelegate().clearCache(); } @Override public final int delete(String arg0) { return getDelegate().delete(arg0); } @Override public final int delete(String arg0, Object arg1) { return getDelegate().delete(arg0, arg1); } @Override public final List<BatchResult> flushStatements() { return getDelegate().flushStatements(); } @Override public final Configuration getConfiguration() { return getDelegate().getConfiguration(); } @Override public final Connection getConnection() { return getDelegate().getConnection(); } @Override public final int insert(String arg0) { return getDelegate().insert(arg0); } @Override public final int insert(String arg0, Object arg1) { return getDelegate().insert(arg0, arg1); } @Override public final void select(String arg0, ResultHandler arg1) { getDelegate().select(arg0, arg1); } @Override public final void select(String arg0, Object arg1, ResultHandler arg2) { getDelegate().select(arg0, arg1, arg2); } @Override public final void select(String arg0, Object arg1, RowBounds arg2, ResultHandler arg3) { getDelegate().select(arg0, arg1, arg2, arg3); } @Override public final <E> List<E> selectList(String arg0) { return getDelegate().selectList(arg0); } @Override public final <E> List<E> selectList(String arg0, Object arg1) { return getDelegate().selectList(arg0, arg1); } @Override public final <E> List<E> selectList(String arg0, Object arg1, RowBounds arg2) { return getDelegate().selectList(arg0, arg1, arg2); } @Override public final <K, V> Map<K, V> selectMap(String arg0, String arg1) { return getDelegate().selectMap(arg0, arg1); } @Override public final <K, V> Map<K, V> selectMap(String arg0, Object arg1, String arg2) { return getDelegate().selectMap(arg0, arg1, arg2); } @Override public final <K, V> Map<K, V> selectMap(String arg0, Object arg1, String arg2, RowBounds arg3) { return getDelegate().selectMap(arg0, arg1, arg2, arg3); } @Override public final <T> T selectOne(String arg0) { return getDelegate().selectOne(arg0); } @Override public final <T> T selectOne(String arg0, Object arg1) { return getDelegate().selectOne(arg0, arg1); } @Override public final int update(String arg0) { return getDelegate().update(arg0); } @Override public final int update(String arg0, Object arg1) { return getDelegate().update(arg0, arg1); } @Override public final void commit() { commit(false); } @Override public final void rollback() { rollback(false); } @Override public final void commit(boolean arg0) { throw new UnsupportedOperationException("operation is not allowed over a managed SqlSession delegate"); } @Override public void rollback(boolean arg0) { throw new UnsupportedOperationException("operation is not allowed over a managed SqlSession delegate"); } @Override public final void close() { throw new UnsupportedOperationException("operation is not allowed over a managed SqlSession delegate"); } @Override public final <T> T getMapper(Class<T> arg0) { return getConfiguration().getMapper(arg0, this); } private static final class ResFactory implements InvocationHandler, MResourceFactory { final SqlSessionFactory factory; final ExecutorType executorType; ResFactory(DataSource dataSource, Configuration config, ExecutorType type) { executorType = type == null ? config.getDefaultExecutorType() : type; config.setEnvironment(new Environment("development", new ManagedTransactionFactory(), SmartDataSource.wrap(dataSource))); this.factory = new SqlSessionFactoryBuilder().build(config); } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (method.getDeclaringClass() == Object.class) return proxyHaEqTostr(proxy, method, args); SqlSession s = factory.openSession(executorType); try { Object ret = method.invoke(s, args); s.commit(true); return ret; } finally { s.close(); } } @Override public MResource newResource(TxInfo txinfo) throws Exception { return new BatisRes(); } private final class BatisRes extends MResource { private final SqlSession session; BatisRes() { session = factory.openSession(executorType); } @Override protected boolean belong(MResourceFactory mfactory) { return ResFactory.this.equals(mfactory); } @Override protected void suspend() { session.flushStatements(); } @Override protected void beforeCompletion() { session.flushStatements(); } @Override protected void afterCompletion() { session.close(); } @Override protected void commit() throws Exception { session.commit(); } @Override protected void rollback() throws Exception { session.rollback(); } @Override protected Object getHandle() { return session; } } } }