Package org.nutz.dao.util

Source Code of org.nutz.dao.util.ExtDaoInvocationHandler

package org.nutz.dao.util;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.sql.DataSource;

import org.nutz.dao.Chain;
import org.nutz.dao.Condition;
import org.nutz.dao.ConnCallback;
import org.nutz.dao.Dao;
import org.nutz.dao.DaoException;
import org.nutz.dao.FieldFilter;
import org.nutz.dao.Sqls;
import org.nutz.dao.TableName;
import org.nutz.dao.entity.Entity;
import org.nutz.dao.entity.MappingField;
import org.nutz.dao.entity.annotation.Table;
import org.nutz.dao.impl.NutDao;
import org.nutz.dao.jdbc.JdbcExpert;
import org.nutz.dao.jdbc.Jdbcs;
import org.nutz.dao.jdbc.ValueAdaptor;
import org.nutz.dao.pager.Pager;
import org.nutz.dao.sql.Sql;
import org.nutz.dao.sql.SqlCallback;
import org.nutz.lang.Lang;
import org.nutz.lang.Strings;
import org.nutz.log.Log;
import org.nutz.log.Logs;
import org.nutz.resource.Scans;
import org.nutz.trans.Molecule;
import org.nutz.trans.Trans;

/**
* Dao 的帮助函数
*
* @author zozoh(zozohtnt@gmail.com)
* @author wendal(wendal1985@gmail.com)
* @author cqyunqin
*/
public abstract class Daos {
   
    private static final Log log = Logs.get();

    public static void safeClose(Statement stat, ResultSet rs) {
        safeClose(rs);
        safeClose(stat);
    }

    public static void safeClose(Statement stat) {
        if (null != stat)
            try {
                stat.close();
            }
            catch (Throwable e) {}
    }

    public static void safeClose(ResultSet rs) {
        if (null != rs)
            try {
                rs.close();
            }
            catch (Throwable e) {}
    }

    public static int getColumnIndex(ResultSetMetaData meta, String colName) throws SQLException {
        if (meta == null)
            return 0;
        int columnCount = meta.getColumnCount();
        for (int i = 1; i <= columnCount; i++)
            if (meta.getColumnName(i).equalsIgnoreCase(colName))
                return i;
        // TODO 尝试一下meta.getColumnLabel?
        log.infof("Can not find @Column(%s) in table/view (%s)", colName, meta.getTableName(1));
        throw Lang.makeThrow(SQLException.class, "Can not find @Column(%s)", colName);
    }

    public static boolean isIntLikeColumn(ResultSetMetaData meta, int index) throws SQLException {
        switch (meta.getColumnType(index)) {
        case Types.BIGINT:
        case Types.INTEGER:
        case Types.SMALLINT:
        case Types.TINYINT:
        case Types.NUMERIC:
            return true;
        }
        return false;
    }

    public static Pager updatePagerCount(Pager pager, Dao dao, Class<?> entityType, Condition cnd) {
        if (null != pager) {
            pager.setRecordCount(dao.count(entityType, cnd));
        }
        return pager;
    }

    public static Pager updatePagerCount(Pager pager, Dao dao, String tableName, Condition cnd) {
        if (null != pager) {
            pager.setRecordCount(dao.count(tableName, cnd));
        }
        return pager;
    }

    public static <T> List<T> queryList(Dao dao, Class<T> klass, String sql_str) {
        Sql sql = Sqls.create(sql_str)
                        .setCallback(Sqls.callback.entities())
                        .setEntity(dao.getEntity(klass));
        dao.execute(sql);
        return sql.getList(klass);
    }

    public static Object query(Dao dao, String sql_str, SqlCallback callback) {
        Sql sql = Sqls.create(sql_str).setCallback(callback);
        dao.execute(sql);
        return sql.getResult();
    }

    public static <T> List<T> queryWithLinks(    final Dao dao,
                                                final Class<T> classOfT,
                                                final Condition cnd,
                                                final Pager pager,
                                                final String regex) {
        Molecule<List<T>> molecule = new Molecule<List<T>>() {
            public void run() {
                List<T> list = dao.query(classOfT, cnd, pager);
                for (T t : list)
                    dao.fetchLinks(t, regex);
                setObj(list);
            }
        };
        return Trans.exec(molecule);
    }

    /*根据Pojo生成数据字典,zdoc格式*/
    public static StringBuilder dataDict(DataSource ds, String...packages) {
        StringBuilder sb = new StringBuilder();
        List<Class<?>> ks = new ArrayList<Class<?>>();
        for (String packageName : packages) {
            ks.addAll(Scans.me().scanPackage(packageName));
        }
        Iterator<Class<?>> it = ks.iterator();
        while (it.hasNext()) {
            Class<?> klass = it.next();
            if (klass.getAnnotation(Table.class) == null)
                it.remove();
        }
        //log.infof("Found %d table class", ks.size());
       
        JdbcExpert exp = Jdbcs.getExpert(ds);
        NutDao dao = new NutDao(ds);
       
        Method evalFieldType;
        try {
            evalFieldType = exp.getClass().getDeclaredMethod("evalFieldType", MappingField.class);
        } catch (Throwable e) {
            throw Lang.wrapThrow(e);
        }
        evalFieldType.setAccessible(true);
        Entity<?> entity = null;
        String line = "-------------------------------------------------------------------\n";
        sb.append("#title:数据字典\n");
        sb.append("#author:wendal\n");
        sb.append("#index:0,1\n").append(line);
        for (Class<?> klass : ks) {
            sb.append(line);
            entity = dao.getEntity(klass);
            sb.append("表名 ").append(entity.getTableName()).append("\n\n");
                if (!Strings.isBlank(entity.getTableComment()))
                    sb.append("表注释: ").append(entity.getTableComment());
                sb.append("\t").append("Java类名 ").append(klass.getName()).append("\n\n");
                sb.append("\t||序号||列名||数据类型||主键||非空||默认值||java属性名||java类型||注释||\n");
                int index = 1;
                for (MappingField field : entity.getMappingFields()) {
                    String dataType;
                    try {
                        dataType = (String) evalFieldType.invoke(exp, field);
                    } catch (Throwable e) {
                        throw Lang.wrapThrow(e); //不可能发生的
                    }
                    sb.append("\t||").append(index++).append("||")
                        .append(field.getColumnName()).append("||")
                        .append(dataType).append("||")
                        .append(field.isPk()).append("||")
                        .append(field.isNotNull()).append("||")
                        .append(field.getDefaultValue(null) == null ? " " : field.getDefaultValue(null)).append("||")
                        .append(field.getName()).append("||")
                        .append(field.getTypeClass().getName()).append("||")
                        .append(field.getColumnComment() == null ? " " : field.getColumnComment()).append("||\n");
                }
        }
        return sb;
    }
   
    /**
     * 查询sql并把结果放入传入的class组成的List中
     */
    public static <T> List<T> query(Dao dao, Class<T> classOfT, String sql, Condition cnd, Pager pager) {
        Sql sql2 = Sqls.queryEntity(sql);
        sql2.setEntity(dao.getEntity(classOfT));
        sql2.setCondition(cnd);
        sql2.setPager(pager);
        dao.execute(sql2);
        return sql2.getList(classOfT);
    }
   
    /**
     * 查询某sql的结果条数
     */
    public static int queryCount(Dao dao, String sql) {
        Sql sql2 = Sqls.fetchLong("select count(1) FROM ("+sql+")");
        dao.execute(sql2);
        return sql2.getInt();
    }
   
    /**
     * 执行一个特殊的Chain(事实上普通Chain也能执行,但不建议使用)
     * @see org.nutz.dao.Chain#addSpecial(String, Object)
     */
    @SuppressWarnings({ "rawtypes" })
    public static int updateBySpecialChain(Dao dao, Entity en, String tableName, Chain chain, Condition cnd) {
        if (en != null)
            tableName = en.getTableName();
        if (tableName == null)
            throw Lang.makeThrow(DaoException.class, "tableName and en is NULL !!");
        final StringBuilder sql = new StringBuilder("UPDATE ").append(tableName).append(" SET ");
        Chain head = chain.head();
        final List<Object> values = new ArrayList<Object>();
        final List<ValueAdaptor> adaptors = new ArrayList<ValueAdaptor>();
        while (head != null) {
            MappingField mf = null;
            if (en != null)
                mf = en.getField(head.name());
            String colName = head.name();
            if (mf != null)
                colName = mf.getColumnName();
            sql.append(colName).append("=");
            if (head.special()) {
              if (head.value() != null && head.value() instanceof String) {
                String str = (String)head.value();
                if (str.length() > 0) {
                  switch (str.charAt(0)) {
            case '+':
            case '-':
            case '*':
            case '/':
            case '%':
            case '&':
            case '^':
            case '|':
              sql.append(colName);
              break;
            }
                }
                }
                sql.append(head.value());
            } else {
                sql.append("?");
                values.add(head.value());
                ValueAdaptor adaptor = Jdbcs.getAdaptorBy(head.value());
                if (mf != null && mf.getAdaptor() != null)
                    adaptor = mf.getAdaptor();
                adaptors.add(adaptor);
            }
            sql.append(" ");
            head = head.next();
            if (head != null)
                sql.append(", ");
        }
        if (cnd != null)
            sql.append(" ").append(cnd.toSql(en));
        if (log.isDebugEnabled())
            log.debug(sql);
        final int[] ints = new int[1];
        dao.run(new ConnCallback() {
            public void invoke(Connection conn) throws Exception {
                PreparedStatement ps = conn.prepareStatement(sql.toString());
                try {
                    for (int i = 0; i < values.size(); i++)
                        adaptors.get(i).set(ps, values.get(i), i + 1);
                    ints[0] = ps.executeUpdate();
                } finally {
                    Daos.safeClose(ps);
                }
            }
        });
        return ints[0];
    }
   
    /**
     * 执行一个特殊的Chain(事实上普通Chain也能执行,但不建议使用)
     * @see org.nutz.dao.Chain#addSpecial(String, Object)
     */
    @SuppressWarnings({ "rawtypes" })
    public static void insertBySpecialChain(Dao dao, Entity en, String tableName, Chain chain) {
        if (en != null)
            tableName = en.getTableName();
        if (tableName == null)
            throw Lang.makeThrow(DaoException.class, "tableName and en is NULL !!");
        final StringBuilder sql = new StringBuilder("INSERT INTO ").append(tableName).append(" (");
        StringBuilder _value_places = new StringBuilder(" VALUES(");
        final List<Object> values = new ArrayList<Object>();
        final List<ValueAdaptor> adaptors = new ArrayList<ValueAdaptor>();
        Chain head = chain.head();
        while (head != null) {
          String colName = head.name();
          MappingField mf = null;
            if (en != null) {
                mf = en.getField(colName);
                if (mf != null)
                  colName = mf.getColumnName();
            }
            sql.append(colName);
           
            if (head.special()) {
              _value_places.append(head.value());
            } else {
                if (en != null)
                    mf = en.getField(head.name());
                _value_places.append("?");
                values.add(head.value());
                ValueAdaptor adaptor = Jdbcs.getAdaptorBy(head.value());
                if (mf != null && mf.getAdaptor() != null)
                    adaptor = mf.getAdaptor();
                adaptors.add(adaptor);
            }
           
            head = head.next();
            if (head != null) {
                sql.append(", ");
                _value_places.append(", ");
            }
        }
        sql.append(")");
        _value_places.append(")");
        sql.append(_value_places);
        if (log.isDebugEnabled())
            log.debug(sql);
        dao.run(new ConnCallback() {
            public void invoke(Connection conn) throws Exception {
                PreparedStatement ps = conn.prepareStatement(sql.toString());
                try {
                    for (int i = 0; i < values.size(); i++)
                        adaptors.get(i).set(ps, values.get(i), i + 1);
                    ps.execute();
                } finally {
                    Daos.safeClose(ps);
                }
            }
        });
    }
   
    public static void createTablesInPackage(Dao dao, String packageName, boolean force) {
      for (Class<?> klass : Scans.me().scanPackage(packageName)) {
      if (klass.getAnnotation(Table.class) != null)
        dao.create(klass, force);
    }
    }
   
  private static Class<?>[] iz = new Class<?>[]{Dao.class};
 
  /**
   * 创建一个带FieldFilter的Dao代理实例. 注意,为避免出错,生成的Dao对象不应该传递到其他方法去.
   * @param dao 原始的Dao实例
   * @param filter 字段过滤器
   * @return 带FieldFilter的Dao代理实例
   */
  public static Dao ext(Dao dao, FieldFilter filter) {
    return ext(dao, filter, null);
  }
 
  /**
   * 创建一个带TableName的Dao代理实例. 注意,为避免出错,生成的Dao对象不应该传递到其他方法去.
   * @param dao 原始的Dao实例
   * @param tableName 动态表名上下文
   * @return 带TableName的Dao代理实例
   */
  public static Dao ext(Dao dao, Object tableName) {
    return ext(dao, null, tableName);
  }
 
  public static Dao ext(Dao dao, FieldFilter filter, Object tableName) {
    if (tableName == null && filter == null)
      return dao;
    ExtDaoInvocationHandler handler = new ExtDaoInvocationHandler(dao, filter, tableName);
    return (Dao) Proxy.newProxyInstance(dao.getClass().getClassLoader(), iz, handler);
  }
}

class ExtDaoInvocationHandler implements InvocationHandler {
 
  protected ExtDaoInvocationHandler(Dao dao, FieldFilter filter, Object tableName) {
    this.dao = dao;
    this.filter = filter;
    this.tableName = tableName;
  }
  public Dao dao;
  public FieldFilter filter;
  public Object tableName;
  public Object invoke(Object proxy, final Method method, final Object[] args) throws Throwable {
   
    final Molecule<Object> m = new Molecule<Object>() {
      public void run() {
        try {
          setObj(method.invoke(dao, args));
        }
        catch (IllegalArgumentException e) {
          throw Lang.wrapThrow(e);
        }
        catch (IllegalAccessException e) {
          throw Lang.wrapThrow(e);
        }
        catch (InvocationTargetException e) {
          throw Lang.wrapThrow(e.getTargetException());
        }
      }
    };
    if (filter != null && tableName != null) {
      TableName.run(tableName, new Runnable() {
        public void run() {
          filter.run(m);
        }
      });
      return m.getObj();
    }
    if (filter != null)
      filter.run(m);
    else
      TableName.run(tableName, m);
    return m.getObj();
  }
}
TOP

Related Classes of org.nutz.dao.util.ExtDaoInvocationHandler

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.