/** 一对多级联更新 */
  public void update(long newIdVal) {
    if (newIdVal <= 0 || this.fields == null || this.fields.size() == 0) return;
    if (this.idVal == null || "0".equals(this.idVal) || "".equals(this.idVal)) {
      return;
    } else if (DAOFactory.getSelectDAO(dsName).selectOne(t, this.idField) == null) {
      // 检查一下当前对象的ID是否存在于数据库
      return;
    }
    // "update {table} set {idCol} = {newIdVal} where {idCol} = {idVal}
    // ; update {relTable} set {fromCol} = {newIdVal} where {fromCol} = {idVal}"
    String format = "update %s set %s = %s where %s = %s ;";
    for (Field f : fields) {
      Method tarGetter = ru.getGetter(f.getName());
      if (tarGetter == null) continue;

      ManyToMany ann = tarGetter.getAnnotation(ManyToMany.class);
      if (ann == null) {
        ann = f.getAnnotation(ManyToMany.class);
        if (ann == null) continue;
      }

      JoinTable join = tarGetter.getAnnotation(JoinTable.class);
      if (join == null) {
        join = f.getAnnotation(JoinTable.class);
        if (join == null) continue;
      }

      JoinColumn[] froms = join.joinColumns();
      if (froms == null || froms.length == 0) continue;

      // 第三方关系表
      String relTable = join.name();
      // 主类在第三方关系表中的字段名
      String from = froms[0].name();

      try {
        // "update {table} set {idCol} = {newIdVal} where {idCol} = {idVal}
        // ; update {relTable} set {fromCol} = {newIdVal} where {fromCol} = {idVal}"
        final String sql1 = String.format(format, table, idColumn, newIdVal, idColumn, idVal);
        final String sql2 = String.format(format, relTable, from, newIdVal, from, idVal);
        Transaction.execute(
            new Trans() {

              @Override
              public void run(Object... args) throws Exception {
                DAOFactory.getUpdateDAO(dsName).updateBySQL(sql1);
                DAOFactory.getUpdateDAO(dsName).updateBySQL(sql2);
              }
            });

      } catch (Exception e) {
        throw new DAOException("", e);
      }
    }
  }
  /**
   * 多对多级联查询 1.当主对象没有包含任何一个关联对象时,默认查询所有与之关联的对象 2.当主对象中包含了关联对象时(含有其id值),则只查询这些关联的对象
   *
   * @param <T>
   * @throws InvocationTargetException
   * @throws IllegalAccessException
   * @throws IllegalArgumentException
   */
  public void select() throws DAOException {
    if (this.fields == null || this.fields.size() == 0) return;
    // select %s from {tarTable} where {referencedColumn} in (select {to} from {relTable} where
    // {from} = {idVal})
    String format = "SELECT %s FROM %s WHERE %s IN (SELECT %s FROM %s WHERE %s = ?) ";
    if (idVal == null || "0".equals(idVal) || "".equals(idVal)) return;

    for (Field f : fields) {
      Method tarGetter = ru.getGetter(f.getName());
      if (tarGetter == null) continue;

      ManyToMany ann = tarGetter.getAnnotation(ManyToMany.class);
      if (ann == null) {
        ann = f.getAnnotation(ManyToMany.class);
        if (ann == null) continue;
      }

      JoinTable join = tarGetter.getAnnotation(JoinTable.class);
      if (join == null) {
        join = f.getAnnotation(JoinTable.class);
        if (join == null) continue;
      }

      JoinColumn[] froms = join.joinColumns();
      if (froms == null || froms.length == 0) continue;

      JoinColumn[] tos = join.inverseJoinColumns();
      if (tos == null || tos.length == 0) continue;

      // 多对多关系目标Class
      Class<?> tarClass = ann.targetEntity();
      if (void.class.isAssignableFrom(tarClass)) {
        tarClass = ClassUtil.getGenericType(f);
      }

      String tarTable = ORMConfigBeanUtil.getTable(tarClass, true);
      // 目标类对应的数据库表Id字段
      String referencedColumn = tos[0].referencedColumnName();
      if (referencedColumn == null || referencedColumn.trim().length() == 0)
        referencedColumn = ORMConfigBeanUtil.getIdColumn(tarClass);

      // 目标类在第三方关系表中的字段名
      String to = tos[0].name();

      // 第三方关系表
      String relTable = join.name();

      // 主类在第三方关系表中的字段名
      String from = froms[0].name();

      try {
        List<?> tarList = null;
        tarList = (List<?>) tarGetter.invoke(t);

        if (tarList != null && tarList.size() > 0) {
          for (int i = 0; i < tarList.size(); i++) {
            Object tarObj = tarList.get(i);
            ReflectUtil tarRu = new ReflectUtil(tarObj);
            String tarIdField = ORMConfigBeanUtil.getIdField(tarClass);
            Method tarIdGetter = tarRu.getGetter(tarIdField);
            Object tarIdValObj = tarIdGetter.invoke(tarObj);
            if (tarIdValObj == null) continue;
            String tarIdVal = String.valueOf(tarIdValObj);
            // 查询 select %s from {tarTable} where {tarIdColumn} = {tarIdVal}
            tarObj =
                DAOFactory.getSelectDAO(dsName)
                    .selectOne(tarClass, new String[] {tarIdField}, new String[] {tarIdVal});
          }
        } else {
          String sql =
              String.format(
                  format,
                  ORMConfigBeanUtil.getSelectAllColumn(tarClass),
                  tarTable,
                  referencedColumn,
                  to,
                  relTable,
                  from);
          // 从数据库中取出与当前主对象id关联的所有目标对象,
          tarList = DAOFactory.getSelectDAO(dsName).selectBySQL(tarClass, sql, idVal);
        }

        // 并注入到当前主对象的属性中
        Method tarSetter = ru.getSetter(f.getName());

        tarSetter.invoke(t, tarList);
      } catch (Exception e) {
        e.printStackTrace();
        throw new DAOException("", e);
      }
    }
  }
  /** 多对一级联查询 1.获取当前idVal,然后作为条件查询出其外键值,接着通过其外键值查出主对象数据,注入到当前 */
  public void select() {
    if (this.fields == null || this.fields.size() == 0) return;
    if (idVal == null || "0".equals(idVal) || "".equals(idVal)) {
      return;
    }
    //		else if (DAOFactory.getSelectDAO(dsName).selectOne(t, this.idField) == null) {
    //			// 检查一下当前对象的ID是否存在于数据库
    //			return;
    //		}

    for (Field f : fields) {
      Method tarGetter = ru.getGetter(f.getName());
      if (tarGetter == null) continue;

      String fk = null;
      OneToOne ann = tarGetter.getAnnotation(OneToOne.class);
      if (ann == null) ann = f.getAnnotation(OneToOne.class);

      if (ann == null) {
        ManyToOne moAn = tarGetter.getAnnotation(ManyToOne.class);
        if (moAn == null) moAn = f.getAnnotation(ManyToOne.class);

        if (moAn == null) continue;
      }
      String refCol = null;
      JoinColumn joinCol = f.getAnnotation(JoinColumn.class);
      if (joinCol == null) joinCol = tarGetter.getAnnotation(JoinColumn.class);

      if (joinCol == null) fk = f.getName() + "_id";
      else {
        fk = joinCol.name();
        refCol = joinCol.referencedColumnName();
      }

      Class<?> tarClass = f.getType();

      if (refCol == null || refCol.trim().length() == 0)
        refCol = ORMConfigBeanUtil.getIdColumn(tarClass);

      String refField = ORMConfigBeanUtil.getField(tarClass, refCol);

      try {
        Object _tarObj = tarGetter.invoke(t);
        Object tarObj = null;
        boolean flag = false;
        if (_tarObj != null) {
          Method refFieldGetter = new ReflectUtil(_tarObj).getGetter(refField);
          if (refFieldGetter != null && refFieldGetter.invoke(_tarObj) != null)
            tarObj = DAOFactory.getSelectDAO(dsName).selectOne(_tarObj, refField);
          else flag = true;
        } else flag = true;

        if (flag) {
          // select * from {tarTable} where {referencedColumn} = (select {fk} from {table} where
          // {idColumn} = {idVal})
          String format = "select %s from %s where %s = (select %s from %s where %s = %s )";
          String tarTable = ORMConfigBeanUtil.getTable(tarClass, true);

          String sql =
              String.format(
                  format,
                  ORMConfigBeanUtil.getSelectAllColumn(tarClass),
                  tarTable,
                  refCol,
                  fk,
                  table,
                  idColumn,
                  idVal);
          List<?> tarList = DAOFactory.getSelectDAO(dsName).selectBySQL(tarClass, sql);
          if (tarList == null || tarList.size() == 0) continue;

          tarObj = tarList.get(0);
        }

        if (tarObj == null) continue;

        Method tarSetter = ru.getSetter(f.getName());
        tarSetter.invoke(t, tarObj);
      } catch (Exception e) {
        throw new DAOException("", e);
      }
    }
  }
  /**
   * 多对多级联删除 1.如果主对象不存在与数据库,不处理 2.否则,检查当前主对象中的关联对象,如果关联对象为空,则删除所有与主对象有关的关联关系。
   * 3.如果当前主对象中含有关联对象,则删除这些关联对象与主对象的关系 4.不会删除主对象
   */
  public void delete() throws DAOException {
    if (this.fields == null || this.fields.size() == 0) return;

    // "delete from {relTable} WHERE {from} = {idVal} ;"
    String format = "delete from %s WHERE %s = ? ";
    if (idVal == null || "0".equals(idVal) || "".equals(idVal)) return;
    else if (DAOFactory.getSelectDAO(dsName).selectOne(t, this.idField) == null) return;

    for (Field f : fields) {
      Method tarGetter = ru.getGetter(f.getName());
      if (tarGetter == null) continue;

      ManyToMany ann = tarGetter.getAnnotation(ManyToMany.class);
      if (ann == null) {
        ann = f.getAnnotation(ManyToMany.class);
        if (ann == null) continue;
      }

      JoinTable join = tarGetter.getAnnotation(JoinTable.class);
      if (join == null) {
        join = f.getAnnotation(JoinTable.class);
        if (join == null) continue;
      }

      JoinColumn[] froms = join.joinColumns();
      if (froms == null || froms.length == 0) continue;

      JoinColumn[] tos = join.inverseJoinColumns();
      if (tos == null || tos.length == 0) continue;

      String relTable = join.name();
      String from = froms[0].name();

      List<?> tarList = null;

      try {
        tarList = (List<?>) tarGetter.invoke(t);
      } catch (Exception e) {
        throw new DAOException(tarGetter + " invoke exception ", e);
      }

      if (tarList == null || tarList.size() == 0) {
        String sql = String.format(format, relTable, from);
        // 删除所有关联记录
        DAOFactory.getUpdateDAO(dsName).updateBySQLWithArgs(sql, idVal);
      } else {
        // 删除指定关联的记录
        String to = tos[0].name();
        Class<?> tarClass = ann.targetEntity();
        if (void.class.isAssignableFrom(tarClass)) {
          tarClass = ClassUtil.getGenericType(f);
        }

        // "delete from {relTable} where {from} = {idVal} and to = {toVal}"
        String _format = "delete from %s where %s = ? and %s = ?";
        for (int i = 0; i < tarList.size(); i++) {
          Object tarObj = tarList.get(i);
          if (tarObj == null) continue;
          ReflectUtil tarRu = new ReflectUtil(tarObj);
          String tarIdField = ORMConfigBeanUtil.getIdField(tarClass);
          Method tarIdGetter = tarRu.getGetter(tarIdField);
          Object toValObj = null;

          try {
            toValObj = tarIdGetter.invoke(tarObj);
          } catch (Exception e) {
            throw new DAOException(tarIdGetter + "invoke exception ", e);
          }

          if (toValObj == null) continue;

          String toVal = String.valueOf(toValObj);
          if (DAOFactory.getSelectDAO(dsName)
                  .selectOne(tarClass, new String[] {tarIdField}, new String[] {toVal})
              == null) continue;

          String _sql = String.format(_format, relTable, from, to);
          DAOFactory.getUpdateDAO(dsName).updateBySQLWithArgs(_sql, idVal, toVal);
        }
      }
    }
  }
  private Object[] assemParams(Class<?>[] paramTypes, Annotation[][] paramAnns) throws Exception {
    Object[] params = new Object[paramTypes.length];
    int pathParamIndex = 0;
    for (int i = 0; i < paramTypes.length; ++i) {
      Annotation[] anns = paramAnns[i];
      Class<?> paramClass = paramTypes[i];
      String[] paramValue = null;
      // ------------------------------------------------------
      // 通过给定class 获取对应的ActionContextObj
      if (Context.class.isAssignableFrom(paramClass)) {
        params[i] = this.context;
        continue;
      }

      if (HttpServletRequest.class.isAssignableFrom(paramClass)) {
        params[i] = this.context.getRequest();
        continue;
      }

      if (HttpServletResponse.class.isAssignableFrom(paramClass)) {
        params[i] = this.context.getResponse();
        continue;
      }

      if (PrintWriter.class.isAssignableFrom(paramClass)) {
        params[i] = this.context.getWriter();
        continue;
      }

      if (ServletOutputStream.class.isAssignableFrom(paramClass)) {
        params[i] = this.context.getOut();
        continue;
      }

      if (HttpSession.class.isAssignableFrom(paramClass)) {
        params[i] = this.context.getSession();
        continue;
      }

      if (ActionProp.class.isAssignableFrom(paramClass)) {
        if (this.context.getActionProp() == null)
          this.context.setActionProp(new ActionProp(this.actionObject.getClass().getName()));

        params[i] = this.context.getActionProp();
        continue;
      }

      if (Validation.class.isAssignableFrom(paramClass)) {
        params[i] = this.context.getValidation();
        continue;
      }

      if (QueryParams.class.isAssignableFrom(paramClass)) {
        params[i] = this.context.getQueryParams();
        continue;
      }

      if (DAO.class.isAssignableFrom(paramClass)) {
        params[i] = new DAOImpl("");
        continue;
      }

      if (InsertDAO.class.isAssignableFrom(paramClass)) {
        params[i] = DAOFactory.getInsertDAO();
        continue;
      }

      if (DeleteDAO.class.isAssignableFrom(paramClass)) {
        params[i] = DAOFactory.getDeleteDAO();
        continue;
      }

      if (UpdateDAO.class.isAssignableFrom(paramClass)) {
        params[i] = DAOFactory.getUpdateDAO();
        continue;
      }

      if (SelectDAO.class.isAssignableFrom(paramClass)) {
        params[i] = DAOFactory.getSelectDAO();
        continue;
      }

      if (DivPageDAO.class.isAssignableFrom(paramClass)) {
        params[i] = DAOFactory.getDivPageDAO();
        continue;
      }

      if (SearchDAO.class.isAssignableFrom(paramClass)) {
        params[i] = DAOFactory.getSearchDAO();
        continue;
      }

      if (CascadeDAO.class.isAssignableFrom(paramClass)) {
        params[i] = DAOFactory.getCascadeDAO();
        continue;
      }

      PathParam pathParamAnn = this.getPathParamAnn(anns);
      if (pathParamAnn != null) {
        paramValue = this.getPathParamValue(pathParamAnn.value());
        params[i] = ClassUtil.getParamVal(paramClass, paramValue[0]);
        continue;
      }

      QueryParam queryParamAnn = this.getQueryParamAnn(anns);

      // 视图模型
      if (queryParamAnn == null && Map.class.isAssignableFrom(paramClass)) {
        params[i] = this.context.getModel();
        continue;
      }

      if (queryParamAnn != null) {
        final String fieldName = queryParamAnn.value();
        if (File.class.isAssignableFrom(paramClass)) {
          if (!this.context.getUploadMap().containsKey(fieldName)) continue;
          List<UploadFile> list = this.context.getUploadMap().get(fieldName);
          if (list == null || list.isEmpty()) continue;

          UploadFile uploadFile = list.get(0);
          File file = uploadFile.getTmpFile();
          params[i] = file;

          continue;
        }

        if (File[].class.isAssignableFrom(paramClass)) {
          if (!this.context.getUploadMap().containsKey(fieldName)) continue;
          List<UploadFile> list = this.context.getUploadMap().get(fieldName);
          if (list == null || list.isEmpty()) continue;
          File[] files = new File[list.size()];
          for (int j = 0; j < files.length; j++) files[j] = list.get(j).getTmpFile();

          params[i] = files;
        }

        if (UploadFile.class.isAssignableFrom(paramClass)) {
          if (!this.context.getUploadMap().containsKey(fieldName)) continue;
          List<UploadFile> list = this.context.getUploadMap().get(fieldName);
          if (list == null || list.isEmpty()) continue;

          UploadFile uploadFile = list.get(0);
          params[i] = uploadFile;

          continue;
        }

        if (UploadFile[].class.isAssignableFrom(paramClass)) {
          if (!this.context.getUploadMap().containsKey(fieldName)) continue;
          List<UploadFile> list = this.context.getUploadMap().get(fieldName);
          if (list == null || list.isEmpty()) continue;

          params[i] = list.toArray(new UploadFile[] {});
        }

        String defaultValue = null;
        DefaultValue defaultValueAnn = this.getDefaultValueAnn(anns);
        if (defaultValueAnn != null) defaultValue = defaultValueAnn.value();

        paramValue = this.getQueryParamValue(fieldName, defaultValue);

        if (java.util.Date.class.isAssignableFrom(paramClass)) {
          params[i] = this.getDateParam(anns, paramValue[0]);
          continue;
        }

        String startName = fieldName;
        if (ClassUtil.isPojo(paramClass)) {
          params[i] = this.injectParam2Pojo(paramClass, startName);
          continue;
        }

        if (Map.class.isAssignableFrom(paramClass)) {
          params[i] = this.injectParam2Map(startName);
          continue;
        }

        if (paramClass.isArray()) params[i] = ClassUtil.getParamVals(paramClass, paramValue);
        else params[i] = ClassUtil.getParamVal(paramClass, paramValue[0]);
      } else {
        // 如果是基本数据类型,则按照排序进行注入
        String[] pathParams = this.context.getActionConfigBean().getPathParams();
        if (pathParams == null) {
          log.warn("QueryParam not found and PathParam not found too");
          continue;
        }

        paramValue = this.getPathParamValue(pathParams[pathParamIndex]);
        params[i] = ClassUtil.getParamVal(paramClass, paramValue[0]);
        pathParamIndex++;
        continue;
      }
    }

    return params;
  }