Package org.nutz.dao.impl

Source Code of org.nutz.dao.impl.DaoSupport$DaoExec

package org.nutz.dao.impl;

import java.sql.Connection;
import java.sql.DatabaseMetaData;

import javax.sql.DataSource;

import org.nutz.dao.ConnCallback;
import org.nutz.dao.DatabaseMeta;
import org.nutz.dao.SqlManager;
import org.nutz.dao.entity.EntityMaker;
import org.nutz.dao.impl.entity.AnnotationEntityMaker;
import org.nutz.dao.impl.sql.NutPojoMaker;
import org.nutz.dao.impl.sql.run.NutDaoExecutor;
import org.nutz.dao.impl.sql.run.NutDaoRunner;
import org.nutz.dao.jdbc.JdbcExpert;
import org.nutz.dao.jdbc.Jdbcs;
import org.nutz.dao.sql.DaoStatement;
import org.nutz.dao.sql.PojoMaker;
import org.nutz.dao.sql.Sql;
import org.nutz.dao.sql.SqlContext;
import org.nutz.log.Log;
import org.nutz.log.Logs;
import org.nutz.trans.Atom;
import org.nutz.trans.Trans;

/**
* Dao 接口实现类的一些基础环境
*
* @author zozoh(zozohtnt@gmail.com)
*/
public class DaoSupport {

    private static final Log log = Logs.get();

    /**
     * 给子类使用的 Dao 的运行器,用来封装事务
     */
    protected DaoRunner runner;

    /**
     * 给子类使用的 Dao 语句执行器,用来具体运行某一条语句
     */
    protected DaoExecutor executor;

    /**
     * 给子类使用数据源
     */
    protected DataSource dataSource;

    /**
     * 给子类使用的数据特殊性的封装
     */
    protected JdbcExpert expert;

    /**
     * 给子类使用的 PojoStatementMaker 接口
     */
    protected PojoMaker pojoMaker;

    /**
     * 给子类使用的 Entity 获取对象
     */
    protected EntityHolder holder;

    /**
     * 数据库的描述
     */
    private DatabaseMeta meta;

    /**
     * SQL 管理接口实现类
     */
    private SqlManager sqlManager;

    public DaoSupport() {
        this.runner = new NutDaoRunner();
        this.executor = new NutDaoExecutor();
    }

    /**
     * @return Sql 管理接口的实例
     */
    public SqlManager sqls() {
        return sqlManager;
    }

    /**
     * @return 当前连接的数据库的一些描述数据
     */
    public DatabaseMeta meta() {
        return meta;
    }

    /**
     * 设置一个新的 Sql 管理接口实例
     *
     * @param sqls
     *            Sql 管理接口实例
     */
    public void setSqlManager(SqlManager sqls) {
        this.sqlManager = sqls;
    }

    /**
     * 设置一个新的 Dao 运行器
     *
     * @param runner
     *            运行器对象
     */
    public void setRunner(DaoRunner runner) {
        this.runner = runner;
    }

    /**
     * 设置一个新的 Dao 语句执行器
     *
     * @param executor
     *            Dao 语句执行器对象
     */
    public void setExecutor(DaoExecutor executor) {
        this.executor = executor;
    }

    /**
     * 设置一个新的 Pojo 语句创建器
     *
     * @param pojoMaker
     *            Pojo 语句创建器
     */
    public void setPojoMaker(PojoMaker pojoMaker) {
        this.pojoMaker = pojoMaker;
    }

    /**
     * @return 当前的 JDBC 专家类
     */
    public JdbcExpert getJdbcExpert() {
        return expert;
    }

    /**
     * 设置新的数据源。
     * <p>
     * 如果有老的数据源需要你在外部手动关闭
     *
     * @param ds
     *            数据源
     */
    public void setDataSource(DataSource ds) {
        if (null != dataSource)
            if (log.isWarnEnabled())
                log.warn("Replaced a running dataSource!");
        dataSource = ds;
        expert = Jdbcs.getExpert(ds);
        pojoMaker = new NutPojoMaker(expert);

        meta = new DatabaseMeta();
        runner.run(dataSource, new ConnCallback() {
            public void invoke(Connection conn) throws Exception {
                DatabaseMetaData dmd = conn.getMetaData();
                meta.setProductName(dmd.getDatabaseProductName());
                meta.setVersion(dmd.getDatabaseProductVersion());
                log.debug("JDBC Driver --> " + dmd.getDriverVersion());
                log.debug("JDBC Name   --> " + dmd.getDriverName());
                if (dmd.getDriverName().contains("mariadb") || dmd.getDriverName().contains("sqlite")) {
                  log.warn("Auto-select fetch size to Integer.MIN_VALUE, enable for ResultSet Streaming");
                  SqlContext.DEFAULT_FETCH_SIZE = Integer.MIN_VALUE;
                }
            }
        });
        if (log.isDebugEnabled())
            log.debug("Database info --> " + meta);

        holder = new EntityHolder(this);
        holder.maker = createEntityMaker();
    }

    public void execute(final Sql... sqls) {
        for (Sql sql : sqls)
            expert.formatQuery(sql);
        _exec(sqls);
    }

    public void run(ConnCallback callback) {
        runner.run(dataSource, callback);
    }

    protected int _exec(final DaoStatement... sts) {
        // 看看是不是都是 SELECT 语句
        boolean isAllSelect = true;
        for (DaoStatement st : sts) {
            if (!st.isSelect()) {
                isAllSelect = false;
                break;
            }
        }
        // 这个是具体执行的逻辑,作为一个回调
        // 后面的逻辑是判断到底应不应该在一个事务里运行它
        DaoExec callback = new DaoExec(sts);

        // 如果强制没有事务或者都是 SELECT,没必要启动事务
        if (sts.length == 1 || isAllSelect || Trans.isTransactionNone()) {
            runner.run(dataSource, callback);
        }
        // 否则启动事务
        // wendal: 还是很有必要的!!尤其是解决insert的@Prev/@Next不在同一个链接的问题
        else {
            Trans.exec(callback);
        }

        // 搞定,返回结果 ^_^
        return callback.re;
    }

    /**
     * 子类可以重写这个类,用来扩展成其他的实体配置方式
     *
     * @return 实体工厂
     */
    protected EntityMaker createEntityMaker() {
        return new AnnotationEntityMaker(dataSource, expert, holder);
    }

    /**
     *
     * @author wendal
     * @since 1.b.44
     */
    protected class DaoExec implements Atom, ConnCallback {
        private DaoStatement[] sts;
        private int re;

        public DaoExec(DaoStatement... sts) {
            this.sts = sts;
        }

        public void run() {
            runner.run(dataSource, this);
        }

        public void invoke(Connection conn) throws Exception {
            for (DaoStatement st : sts) {
                if (st == null) {
                    if (log.isInfoEnabled())
                        log.info("Found a null DaoStatement(SQL), ingore it ~~");
                    continue;
                }
                executor.exec(conn, st);
                re += st.getUpdateCount();
            }
        }
    }
}
TOP

Related Classes of org.nutz.dao.impl.DaoSupport$DaoExec

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.