zcu.xutil.orm.MyBatisSession.java Source code

Java tutorial

Introduction

Here is the source code for zcu.xutil.orm.MyBatisSession.java

Source

/*
 * 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;
            }
        }
    }
}