jbase引入连接池

网站主题和代码生成器完事之后,ORM成为主要工作,之前只是搭了ORM的大体结构,没有详细优化和实现。这次引入连接池、把连接串信息从配置取、调整抛出异常。

连接池包选择c3p0,因为他稳定,用的多,下载引入c3p0包
在这里插入图片描述

调整IDbFactory接口

package LIS.DAL.ORM.DBUtility;

import java.sql.Connection;

/**
 * 数据驱动层接口,ORM基于此加载驱动和执行SQL,不同数据库实现该接口配置到容器即可
 */
public interface IDbFactory {
    /**
     * 得到数据库类型
     * @return
     */
    String GetStrDbType();

    /**
     * 得到数据库连接串
     * @return
     */
    String GetConnectionString() throws Exception;

    /**
     * 得到数据库用户名
     * @return
     */
    String GetUserName() throws Exception;

    /**
     * 得到数据库密码
     * @return
     */
    String GetUserPass() throws Exception;

    /**
     * 得到返回查询的RowID的SQL语句
     * @return
     */
    String GetReturnRowIDSql();

    /**
     * 处理表名称,用来适配不同数据库间的属性命名差异
     * @param tableName
     * @return
     */
    String DealTableName(String tableName);

    /**
     * 处理属性名字
     * @param propertyName
     * @return
     */
    String DealPropertyName(String propertyName);

    /**
     * DealSqlPara
     * @param propertyName
     * @return
     */
    String DealSqlPara(String propertyName);

    /**
     * 加载驱动
     * @return
     */
    String GetDriver();

    /**
     * 得到初始化连接串大小
     * @return
     */
    int GetInitPoolSize() throws Exception;

    /**
     * 得到最大连接串大小
     * @return
     */
    int GetMaxPoolSize() throws Exception;
}

实现连接串工具类
在这里插入图片描述

package LIS.DAL.ORM.DBUtility;
import com.mchange.v2.c3p0.ComboPooledDataSource;

import java.sql.Connection;
import java.util.Properties;

import LIS.DAL.ORM.DBUtility.IDbFactory;

/**
 * 连接池工具类
 */
public class C3P0Util {

    /**
     * 初始化连接池
     * @param factory 数据库驱动接口
     */
    public static ComboPooledDataSource GetConnPool(IDbFactory factory) throws Exception
    {
        ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
        //给数据源 comboPooledDataSource 设置相关的参数
        //注意:连接管理是由 comboPooledDataSource 来管理
        comboPooledDataSource.setDriverClass(factory.GetDriver());
        comboPooledDataSource.setJdbcUrl(factory.GetConnectionString());
        comboPooledDataSource.setUser(factory.GetUserName());
        comboPooledDataSource.setPassword(factory.GetUserPass());

        //设置初始化连接数
        comboPooledDataSource.setInitialPoolSize(factory.GetInitPoolSize());

        //最大连接数
        comboPooledDataSource.setMaxPoolSize(factory.GetMaxPoolSize());
        return comboPooledDataSource;
    }

    /**
     * 得到数据库连接对象
     * @return
     * @throws Exception
     */
    public static Connection GetConnection(ComboPooledDataSource comboPooledDataSource) throws Exception
    {
        //这个方法就是从 DataSource 接口实现的
        Connection connection = comboPooledDataSource.getConnection();
        return connection;
    }

}

调整DBManager

package LIS.DAL.ORM.DBUtility;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Savepoint;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

import LIS.DAL.ORM.DBUtility.C3P0Util;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import LIS.DAL.ORM.DBUtility.IDbFactory;

/**
 * 连接和事务管理
 */
public class DBManager {
    /**
     * 驱动名称
     */
    private String factoryName="";

    /**
     * 当前对象的驱动
     */
    private IDbFactory factory=null;


    /**
     * 存数据库连接对象
     */
    private Connection connection=null;

    /**
     * 为每个数据库驱动存储工厂
     */
    private static ConcurrentHashMap<String, IDbFactory> hsFact = new ConcurrentHashMap<>();

    /**
     * 为每个数据库驱动存储连接池
     */
    private static ConcurrentHashMap<String, ComboPooledDataSource> hsPoll = new ConcurrentHashMap<>();

    /**
     * 得到驱动对象
     * @param factoryName
     * @return
     */
    public IDbFactory GetIDbFactory(String factoryName)
    {
        if(factory==null)
        {
            factory=hsFact.get(factoryName);
        }
        return factory;
    }


    /**
     * 尝试初始化连接池
     * @param factoryName
     */
    public static void TryInitConnPool(String factoryName) throws Exception
    {
        if(factoryName=="")
        {
            factoryName="LisMianDbFactory";
        }
        if(!hsPoll.containsKey(factoryName))
        {
            IDbFactory factory=LIS.Core.Context.ObjectContainer.GetTypeObject(factoryName);
            hsPoll.put(factoryName,C3P0Util.GetConnPool(factory));
            if(!hsFact.containsKey(factoryName))
            {
                hsFact.put(factoryName,factory);
            }
        }
    }

    /**
     * 构造函数
     * @param factName 驱动配置名称
     * @throws Exception
     */
    public DBManager(String factName) throws Exception
    {
        factoryName=factName;
        TryInitConnPool(factoryName);
    }

    /**
     * 存数据库连接对象
     */
    public Connection Connection() throws Exception
    {
        if(connection==null)
        {
            connection=hsPoll.get(factoryName).getConnection();
        }
        return connection;
    }

    /**
     * 标识是否开启事务
     */
    public boolean Hastransaction = false;

    /**
     * 存储开启多次事务的保存点,每次调用BeginTransaction开启事务是自动创建保存点
     */
    public LinkedList<Savepoint> Transpoints = new LinkedList<Savepoint>();

    /**
     * 获取开启的事务层级
     * @return
     */
    public int GetTransactionLevel()
    {
        return this.Transpoints.size();
    }

    /**
     * 释放数据库连接
     * @return true成功释放,false释放失败
     */
    public boolean Close() throws Exception
    {
        connection.close();
        connection=null;
        return true;
    }


    /**
     * 此方法开启事务
     * @return  true开启事务成功,false开始事务失败
     */
    public boolean BeginTransaction() throws Exception
    {
        try
        {
            this.Connection().setAutoCommit(false);
            this.Hastransaction = true;
            Savepoint savepoint = this.Connection().setSavepoint();
            Transpoints.addLast(savepoint);
            return true;
        }

        catch (SQLException sqle)
        {
            LIS.Core.Util.LogUtils.WriteExceptionLog("开启事务失败!" + sqle.getMessage(), sqle);
        }
        return false;
    }

    /**
     * 回滚上一层事务
     * @return true回滚事务成功,false回滚事务失败
     */
    public boolean RollTransaction() throws Exception
    {
        //未开启事务时,算回滚事务成功
        if (!this.Hastransaction)
        {
            return true;
        }
        try
        {
            if (this.Transpoints.size() == 0)
            {
                this.Connection().rollback();
                this.Hastransaction = false;
            }
            else
            {
                Savepoint point = this.Transpoints.poll();
                this.Connection().rollback(point);
            }
            return true;
        }
        catch (SQLException sqle)
        {
            LIS.Core.Util.LogUtils.WriteExceptionLog("事务回滚失败!" + sqle.getMessage(),sqle);
            throw sqle;
        }
        finally
        {
            if (!this.Hastransaction)
            {
                Close();
            }
        }
    }

    /**
     * 回滚开启的全部事务
     * @return true回滚事务成功,false回滚事务失败
     */
    public boolean RollTransactionAll() throws Exception
    {
        //未开启事务时,算回滚事务成功
        if (!this.Hastransaction)
        {
            return true;
        }
        try
        {
            this.Connection().rollback();
            this.Hastransaction = false;
            return true;
        }
        catch (SQLException sqle)
        {
            LIS.Core.Util.LogUtils.WriteExceptionLog("回滚所有事务层级失败!" + sqle.getMessage(),sqle);
            throw sqle;
        }
        finally
        {
            Close();
        }
    }

    /**
     * 提交事务
     * @return true提交事务成功,false提交事务失败
     */
    public boolean CommitTransaction() throws Exception
    {
        try
        {
            this.Connection().commit();
            this.Hastransaction = false;
            return true;
        }
        catch (SQLException sqle)
        {
            LIS.Core.Util.LogUtils.WriteExceptionLog("提交事务失败!" + sqle.getMessage(),sqle);
        }
        finally
        {
            //提交事务,不论成功与否,释放数据库连接
            try
            {
                Close();
            }
            catch (Exception ex)
            {

            }
        }
        return false;
    }

}

常用api实现

package LIS.DAL.ORM.EntityManager;

import java.lang.reflect.Type;
import java.sql.*;
import java.util.List;
import java.util.*;

import LIS.Core.CustomAttributes.FrekeyAttribute;
import LIS.Core.Dto.*;
import LIS.Model.Bussiness.Sessions;
import LIS.DAL.ORM.DBUtility.JsonHelper;
import LIS.DAL.ORM.DBUtility.DBManager;
import LIS.DAL.ORM.Common.TableInfo;
import LIS.DAL.ORM.DBUtility.DBParaUtil;

public class EntityManagerImpl implements LIS.DAL.ORM.EntityManager.IEntityManager {
    /**
     * 数据库连接容器驱动名称
     */
    private String factoryName = "LisMianDbFactory";

    /// <summary>
    /// 存会话信息
    /// </summary>
    LIS.Model.Bussiness.Sessions Session = null;

    /**
     * 管理数据库连接
     */
    private DBManager manager = null;

    /**
     * 无参构造函数
     */
    public EntityManagerImpl() {
    }

    /**
     * 类对象代码块实现对数据库连接的初始化,操作数据库的增删改查及事务都使用对象完成
     *
     * @param dbFactoryKey 配置名称
     */
    public EntityManagerImpl(String dbFactoryKey) {
        factoryName = dbFactoryKey;
    }

    /**
     * 安装会话和数据库驱动配置对象主键初始化数据管理器
     *
     * @param session      会话对象
     * @param dbFactoryKey 配置名称
     */
    public EntityManagerImpl(Sessions session, String dbFactoryKey) {
        Session = session;
        factoryName = dbFactoryKey;
    }

    /**
     * 控制事务
     */
    public DBManager Transaction = null;

    /**
     * 开启事务,该方法初始化一个新的事务
     */
    public void BeginTransaction() throws Exception {
        Manager().BeginTransaction();
    }

    /**
     * 得到管理器
     *
     * @return
     */
    public DBManager Manager() throws Exception {
        if (manager == null) {
            manager = new DBManager(factoryName);
            //供事务操作的对象
            Transaction = manager;
        }
        return manager;
    }


    /**
     * 保存对象
     *
     * @param entity 实体对象
     * @param <T>    实体类型约束
     * @throws SQLException 执行抛出SQL异常
     * @return影响行数
     */
    @Override
    public <T> int Save(T entity) throws Exception {
        PreparedStatement stmt = null;
        try {
            //根据实体对象获取表信息
            TableInfo tableInfo = LIS.DAL.ORM.Common.ModelToSqlUtil.GetTypeInfo(entity);
            //带出参数的对象
            HashParam hash = new HashParam();
            //获取插入SQL语句
            String sql = LIS.DAL.ORM.Common.ModelToSqlUtil.GetInsertSqlByTableInfo(Manager().GetIDbFactory(factoryName), tableInfo, hash, false);
            //写SQL日志
            LIS.Core.Util.LogUtils.WriteSqlLog("执行插入SQL:" + sql);
            //声明式SQL,并设置参数
            stmt = Manager().Connection().prepareStatement(sql);
            String paraSql = DBParaUtil.SetDBPara(stmt, hash.GetParam());
            int row = stmt.executeUpdate();
            LIS.Core.Util.LogUtils.WriteSqlLog("参数:" + paraSql);
            return row;
        } catch (Exception ex) {
            //操作异常,判断如果开启事务,则回滚事务
            if (Manager().Hastransaction) {
                if (!Manager().RollTransaction()) {
                    throw new SQLException("保存数据失败!" + ex.getMessage() + ";回滚事务失败。");
                }
            }
            throw new SQLException("保存数据失败!" + ex.getMessage());
        }
        //操作结束释放资源
        finally {
            if (stmt != null) {
                stmt.close();
            }
            //如果上层调用未开启事务,则调用结束释放数据库连接
            if (!Manager().Hastransaction) {
                manager.Close();
            }
        }
    }

    /**
     * 保存对象
     *
     * @param entity   实体对象
     * @param outParam 输出执行成功或失败信息
     * @param <T>      实体类型约束
     * @return影响行数
     */
    @Override
    public <T> int Save(T entity, OutParam outParam) throws Exception {
        int row = 0;
        PreparedStatement stmt = null;
        boolean innerT = false;     //标识是否内部开启事务
        String sql = "";
        try {
            //根据实体对象获取表信息
            LIS.DAL.ORM.Common.TableInfo tableInfo = LIS.DAL.ORM.Common.ModelToSqlUtil.GetTypeInfo(entity);
            HashParam hash = new HashParam();
            //获取插入SQL语句
            sql = LIS.DAL.ORM.Common.ModelToSqlUtil.GetInsertSqlByTableInfo(Manager().GetIDbFactory(factoryName), tableInfo, hash, false);
            //写SQL日志
            LIS.Core.Util.LogUtils.WriteSqlLog("执行插入SQL:" + sql + ";SQL参数:" + LIS.Core.Util.JsonUtil.Object2Json(hash.GetParam()));
            //声明式SQL,并设置参数
            stmt = Manager().Connection().prepareStatement(sql);
            String paraSql = DBParaUtil.SetDBPara(stmt, hash.GetParam());
            row = stmt.executeUpdate();
            ResultSet rowID = stmt.getGeneratedKeys();
            LIS.Core.Util.LogUtils.WriteSqlLog("参数:" + paraSql);
            //保存成功返回记录主键,返回影响记录数 1
            if (row == 1) {
                outParam.Message = rowID;
            } else {
                outParam.Code = OutStatus.ERROR;
                outParam.Message = "保存数据失败,执行保存返回:" + row;
            }
            return row;
        } catch (Exception ex) {
            outParam.Code = OutStatus.ERROR;
            //操作异常,判断如果开启事务,则回滚事务
            if (Manager().Hastransaction) {
                if (!Manager().RollTransaction()) {
                    outParam.Message = "保存数据失败!" + ex.getMessage() + ";回滚事务失败。";
                }
            }
            outParam.Message = "保存数据失败!" + ex.getMessage() + "执行SQL:" + sql;
        }
        //操作结束释放资源
        finally {
            if (stmt != null) {
                stmt.close();
            }
            //如果上层调用未开启事务,则调用结束释放数据库连接
            if (!Manager().Hastransaction) {
                Manager().Close();
            }
        }
        return row;
    }

    /**
     * 更新实体对象
     *
     * @param entity        实体对象
     * @param param         更新条件,有条件就按条件更新,没有条件就按主键更新
     * @param outParam      输出执行成功或失败的信息
     * @param updateColName 更新属性名集合,无属性则更新实体的所有属性
     * @param joiner        连接符,为空或不给则按则按且连接,给的话长度应该比参数长度少1,如: and
     * @param operators     操作符,为空或不给的话各条件按等来比较,给的话长度应该跟参数长度一样,如: !=
     * @param <T>           类型限定符
     * @return 影响行数
     */
    @Override
    public <T> int Update(T entity, HashParam param, OutParam outParam, List<String> updateColName, List<String> joiner, List<String> operators) throws Exception {
        PreparedStatement stmt = null;
        if (outParam == null) outParam = new OutParam();
        int row = 0;
        boolean innerT = false;     //标识是否内部开启事务
        try {
            //根据实体获取表信息
            LIS.DAL.ORM.Common.TableInfo tableInfo = LIS.DAL.ORM.Common.ModelToSqlUtil.GetTypeInfo(entity);
            HashParam hash = new HashParam();
            //获取更新的SQL语句
            String sql = LIS.DAL.ORM.Common.ModelToSqlUtil.GetUpdateSqlByTableInfo(Manager().GetIDbFactory(factoryName), tableInfo, param, updateColName, joiner, operators, hash);
            //写SQL日志
            LIS.Core.Util.LogUtils.WriteSqlLog("执行更新SQL:" + sql);
            //声明式SQL,并且设置参数
            stmt = Manager().Connection().prepareStatement(sql);
            String paraSql = DBParaUtil.SetDBPara(stmt, hash.GetParam());
            row = stmt.executeUpdate();
            LIS.Core.Util.LogUtils.WriteSqlLog("参数:" + paraSql);
            outParam.Code = OutStatus.SUCCESS;
            outParam.Message = "更新数据成功。";
            return row;
        } catch (Exception ex) {
            //操作异常,判断如果开启了事务,就回滚事务
            outParam.Code = OutStatus.ERROR;
            if (Manager().Hastransaction) {
                if (!Manager().RollTransaction()) {
                    outParam.Message = "更新数据失败!" + ex.getMessage() + ";回滚事务失败。";
                }
            }
            outParam.Message = "更新数据失败!" + ex.getMessage();
        }
        //操作结束释放资源
        finally {
            if (stmt != null) {
                stmt.close();
            }
            //如果上层调用未开启事务,则调用结束释放数据库连接
            if (!Manager().Hastransaction) {
                Manager().Close();
            }
        }
        return row;
    }

    /**
     * 根据条件删除记录
     *
     * @param entity    实体对象
     * @param param     删除条件,有条件按条件删除,没有条件按主键删除
     * @param outParam  输出执行成功或失败的信息
     * @param joiner    多条件逻辑连接符,为空或不给则按则按且连接,给的话长度应该比参数长度少1,如: and
     * @param operators 操作符,为空或不给的话各条件按等来比较,给的话长度应该跟参数长度一样,如: !=
     * @param <T>       类型限定符
     * @return 影响行数
     */
    @Override
    public <T> int Remove(T entity, HashParam param, OutParam outParam, List<String> joiner, List<String> operators) throws Exception {
        PreparedStatement stmt = null;
        if (outParam == null) outParam = new OutParam();
        int row = 0;
        try {
            //根据实体对象获取表信息
            LIS.DAL.ORM.Common.TableInfo tableInfo = LIS.DAL.ORM.Common.ModelToSqlUtil.GetTypeInfo(entity);
            HashParam hash = new HashParam();
            //获取删除SQL语句
            String sql = LIS.DAL.ORM.Common.ModelToSqlUtil.GetDeleteSqlByTableInfo(Manager().GetIDbFactory(factoryName), tableInfo, param, joiner, operators, hash);
            //写SQL日志
            LIS.Core.Util.LogUtils.WriteSqlLog("执行删除SQL:" + sql);
            //声明式SQL,并设置参数
            stmt = Manager().Connection().prepareStatement(sql);
            String paraSql = DBParaUtil.SetDBPara(stmt, hash.GetParam());
            row = stmt.executeUpdate();
            LIS.Core.Util.LogUtils.WriteSqlLog("参数:" + paraSql);
            outParam.Code = OutStatus.SUCCESS;
            outParam.Message = "删除数据成功。";
            return row;
        } catch (Exception ex) {
            //操作异常,判断如果开启了事务,就回滚事务
            outParam.Code = OutStatus.ERROR;
            if (Manager().Hastransaction) {
                if (!Manager().RollTransaction()) {
                    outParam.Message = "更新数据失败!" + ex.getMessage() + ";回滚事务失败。";
                }
            }
            outParam.Message = "更新数据失败!" + ex.getMessage();
        }
        //操作结束释放资源
        finally {
            if (stmt != null) {
                stmt.close();
            }
            //如果上层调用未开启事务,则调用结束释放数据库连接
            if (!Manager().Hastransaction) {
                Manager().Close();
            }
        }
        return row;
    }

    /**
     * 根据ID删除记录
     *
     * @param entity   实体对象
     * @param outParam 输出信息
     * @param <T>      实体类型限定
     * @return 影响行数
     */
    public <T> int Remove(T entity, OutParam outParam) throws Exception {
        return Remove(entity, null, outParam, null, null);
    }

    /**
     * 批量删除对象,发生错误后全部回滚,批量操作
     *
     * @param entity 实体对象
     * @param idList 对象ID集合
     * @param <T>    实体限定类型
     * @return 影响行数
     */
    public <T> int RemoveLot(T entity, List<Object> idList) throws Exception {
        //无删除数据直接返回
        if (idList == null || idList.size() == 0) return 0;
        //记录影响行数
        int row = 0;
        //记录处理删除数据id
        String curId;
        //记录调用方法出参
        OutParam outParam = new OutParam();
        HashParam param = new HashParam();
        try {
            for (int i = 0; i < idList.size(); i++) {
                Object id = idList.get(i);
                LIS.DAL.ORM.Common.TableInfo tableInfo = LIS.DAL.ORM.Common.ModelToSqlUtil.GetTypeInfo(entity);
                String idName = tableInfo.ID.Key;
                param.Clear();
                param.Add(idName, id);
                curId = id.toString();
                int ret = Remove(entity, param, outParam, null, null);
                if (outParam.Code == OutStatus.ERROR) {
                    throw new Exception("删除记录失败!记录id:" + curId);
                }
                //累计删除成功的记录数
                row += ret;
            }
            return row;
        } catch (Exception ex) {
            row = 0;
            if (Manager().Hastransaction) {
                if (!Manager().RollTransactionAll()) {
                    LIS.Core.Util.LogUtils.WriteSqlLog(ex.getMessage() + ";回滚事务失败!");
                }
            }
            LIS.Core.Util.LogUtils.WriteSqlLog("批量删除数据异常:" + ex.getMessage());
        }
        return row;
    }

    /**
     * 码表查询
     *
     * @param modelName   实体名称
     * @param param       查询条件参数,数据列名和值的键对
     * @param orderField  排序字段,如RowID Desc
     * @param returnCount 是否输出数据总行数
     * @param pageSize    页大小。为-1,无条件查所有数据
     * @param pageIndex   第几页。为-1,无条件查询所有数据
     * @param fields      显示字段,为空显示所有列,字段名称以英文','隔开,如:RowID,Code,Name
     * @param joiner      连接符,为空或不给则查询条件以且连接,给的话长度比参数少1
     * @param operators   操作符,为空或不给的话条件以等来判断,给的话与参数长度一致。如!=,<,>
     * @return
     */
    @Override
    public String QueryAllWithFKByName(String modelName, HashParam param, String orderField, boolean returnCount, int pageSize, int pageIndex, String fields, List<String> joiner, List<String> operators) throws Exception {
        List<ParamDto> pdto = null;
        if (param != null) {
            pdto = param.GetParam();
        }
        return QueryAllWithFKByName(modelName, pdto, orderField, returnCount, pageSize, pageIndex, fields, joiner, operators);
    }

    /**
     * 码表查询
     *
     * @param modelName   实体名称
     * @param param       查询条件参数,数据列名和值的键对
     * @param orderField  排序字段,如RowID Desc
     * @param returnCount 是否输出数据总行数
     * @param pageSize    页大小。为-1,无条件查所有数据
     * @param pageIndex   第几页。为-1,无条件查询所有数据
     * @param fields      显示字段,为空显示所有列,字段名称以英文','隔开,如:RowID,Code,Name
     * @param joiner      连接符,为空或不给则查询条件以且连接,给的话长度比参数少1
     * @param operators   操作符,为空或不给的话条件以等来判断,给的话与参数长度一致。如!=,<,>
     * @return
     */
    @Override
    public String QueryAllWithFKByName(String modelName, List<ParamDto> param, String orderField, boolean returnCount, int pageSize, int pageIndex, String fields, List<String> joiner, List<String> operators) throws Exception {
        try {
            Class c = GetTypeByName(modelName);
            if (c != null) {
                Object o = c.getConstructor().newInstance();
                return QueryAllWithFK(o, param, orderField, returnCount, pageSize, pageIndex, fields, joiner, operators);
            }
        } catch (Exception ex) {
            LIS.Core.Util.LogUtils.WriteExceptionLog("调用ORM的QueryAllByName异常", ex);
        }
        return "";
    }

    /**
     * 码表查询,不分页
     *
     * @param modelName   实体名称
     * @param param       查询条件参数,数据列名和值的键对
     * @param orderField  排序字段,如RowID Desc
     * @param returnCount 是否输出数据总行数
     * @param fields      显示字段,为空显示所有列,字段名称以英文','隔开,如:RowID,Code,Name
     * @param joiner      连接符,为空或不给则查询条件以且连接,给的话长度比参数少1
     * @param operators   操作符,为空或不给的话条件以等来判断,给的话与参数长度一致。如!=,<,>
     * @return
     */
    @Override
    public String QueryAllWithFKByName(String modelName, HashParam param, String orderField, boolean returnCount, String fields, List<String> joiner, List<String> operators) throws Exception {
        return QueryAllWithFKByName(modelName, param, orderField, returnCount, -1, -1, fields, joiner, operators);
    }

    /**
     * 码表查询,不分页
     *
     * @param modelName   实体名称
     * @param param       查询条件参数,数据列名和值的键对
     * @param orderField  排序字段,如RowID Desc
     * @param returnCount 是否输出数据总行数
     * @param fields      显示字段,为空显示所有列,字段名称以英文','隔开,如:RowID,Code,Name
     * @param joiner      连接符,为空或不给则查询条件以且连接,给的话长度比参数少1
     * @param operators   操作符,为空或不给的话条件以等来判断,给的话与参数长度一致。如!=,<,>
     * @return
     */
    @Override
    public String QueryAllWithFKByName(String modelName, List<ParamDto> param, String orderField, boolean returnCount, String fields, List<String> joiner, List<String> operators) throws Exception {
        return QueryAllWithFKByName(modelName, param, orderField, returnCount, -1, -1, fields, joiner, operators);
    }


    /**
     * 根据条件+字段查询,查询结果按指定的页面把数据按JSON返回;
     * 该方法会把外键关联的字段查出来,用来取缔试图的查询
     *
     * @param model       实体对象
     * @param param       查询条件参数,数据列名和值的键对
     * @param orderFields 排序字段,如RowID Desc
     * @param returnCount 是否输出数据总行数
     * @param pageSize    页大小。为-1,无条件查所有数据
     * @param pageIndex   第几页。为-1,无条件查询所有数据
     * @param fields      显示字段,为空显示所有列,字段名称以英文','隔开,如:RowID,Code,Name
     * @param joiner      连接符,为空或不给则查询条件以且连接,给的话长度比参数少1
     * @param operators   操作符,为空或不给的话条件以等来判断,给的话与参数长度一致。如!=,<,>
     * @param <T>         限定实体类型
     * @return 查询json串
     */
    @Override
    public <T> String QueryAllWithFK(T model, HashParam param, String orderFields, boolean returnCount, int pageSize, int pageIndex, String fields, List<String> joiner, List<String> operators) throws Exception {
        List<ParamDto> pdto = null;
        if (param != null) {
            pdto = param.GetParam();
        }
        return QueryAllWithFK(model, pdto, orderFields, returnCount, pageSize, pageIndex, fields, joiner, operators);
    }

    /**
     * 根据条件+字段查询,查询结果按指定的页面把数据按JSON返回;
     * 该方法会把外键关联的字段查出来,用来取缔试图的查询
     * 不分页
     *
     * @param model       实体对象
     * @param param       查询条件参数,数据列名和值的键对
     * @param orderFields 排序字段,如RowID Desc
     * @param returnCount 是否输出数据总行数
     * @param fields      显示字段,为空显示所有列,字段名称以英文','隔开,如:RowID,Code,Name
     * @param joiner      连接符,为空或不给则查询条件以且连接,给的话长度比参数少1
     * @param operators   操作符,为空或不给的话条件以等来判断,给的话与参数长度一致。如!=,<,>
     * @param <T>         限定实体类型
     * @return 查询json串
     */
    @Override
    public <T> String QueryAllWithFK(T model, HashParam param, String orderFields, boolean returnCount, String fields, List<String> joiner, List<String> operators) throws Exception {
        List<ParamDto> pdto = null;
        if (param != null) {
            pdto = param.GetParam();
        }
        return QueryAllWithFK(model, pdto, orderFields, returnCount, fields, joiner, operators);
    }

    /**
     * 根据条件+字段查询,查询结果按指定的页面把数据按JSON返回;
     * 该方法会把外键关联的字段查出来,用来取缔试图的查询
     * 不分页
     *
     * @param model       实体对象
     * @param param       查询条件参数,数据列名和值的键对
     * @param orderFields 排序字段,如RowID Desc
     * @param returnCount 是否输出数据总行数
     * @param fields      显示字段,为空显示所有列,字段名称以英文','隔开,如:RowID,Code,Name
     * @param joiner      连接符,为空或不给则查询条件以且连接,给的话长度比参数少1
     * @param operators   操作符,为空或不给的话条件以等来判断,给的话与参数长度一致。如!=,<,>
     * @param <T>         限定实体类型
     * @return 查询json串
     */
    @Override
    public <T> String QueryAllWithFK(T model, List<ParamDto> param, String orderFields, boolean returnCount, String fields, List<String> joiner, List<String> operators) throws Exception {
        return QueryAllWithFK(model, param, orderFields, returnCount, -1, -1, fields, joiner, operators);
    }

    /**
     * 根据条件+字段查询,查询结果按指定的页面把数据按JSON返回;
     * 该方法会把外键关联的字段查出来,用来取缔试图的查询
     *
     * @param model       实体对象
     * @param param       查询条件参数,数据列名和值的键对
     * @param orderFields 排序字段,如RowID Desc
     * @param returnCount 是否输出数据总行数
     * @param pageSize    页大小。为-1,无条件查所有数据
     * @param pageIndex   第几页。为-1,无条件查询所有数据
     * @param fields      显示字段,为空显示所有列,字段名称以英文','隔开,如:RowID,Code,Name
     * @param joiner      连接符,为空或不给则查询条件以且连接,给的话长度比参数少1
     * @param operators   操作符,为空或不给的话条件以等来判断,给的话与参数长度一致。如!=,<,>
     * @param <T>         限定实体类型
     * @return 查询json串
     */
    @Override
    public <T> String QueryAllWithFK(T model, List<ParamDto> param, String orderFields, boolean returnCount, int pageSize, int pageIndex, String fields, List<String> joiner, List<String> operators) throws Exception {
        //json数据组装容器
        StringBuilder jsonsb = new StringBuilder();
        //查询起始行数
        int fromRow = -1;
        //查询结束行数
        int toRow = -1;
        //是否查询全部数据
        boolean findAll = false;
        //记录总行数
        int rowCount = 0;
        if (fields != null && !fields.isEmpty()) {
            fields = "," + fields + ",";
        }
        //如果未传入分页数据其中一个未-1,则认为部分页而查询所有数据
        if (pageIndex == -1 || pageSize == -1) {
            findAll = true;
        }
        //计算查询起始和结束行数
        else {
            fromRow = (pageIndex - 1) * pageSize;
            toRow = pageIndex * pageSize;
        }
        PreparedStatement pstat = null;
        ResultSet rst = null;
        LIS.DAL.ORM.Common.TableInfo tableInfo = LIS.DAL.ORM.Common.ModelToSqlUtil.GetTypeInfo(model);

        //根据表信息将查询参数组装成Select SQL
        String sql = LIS.DAL.ORM.Common.ModelToSqlUtil.GetSelectSqlByTableInfo(Manager().GetIDbFactory(factoryName), tableInfo, param, operators, joiner, orderFields, true);
        //写SQL日志
        LIS.Core.Util.LogUtils.WriteSqlLog("执行QueryAllWithFK返回String查询SQL:" + sql);
        //如果返回总行数,返回总行数写法
        if (returnCount) {
            jsonsb.append("{");
            jsonsb.append("\"rows\":[");
        }
        //否则采用普通数组写法
        else {
            jsonsb.append("[");
        }
        StringBuilder rowAllsb = new StringBuilder();
        try {
            pstat = Manager().Connection().prepareStatement(sql);
            String paraSql = DBParaUtil.SetDBPara(pstat, param);
            rst = pstat.executeQuery();
            LIS.Core.Util.LogUtils.WriteSqlLog("参数:" + paraSql);
            //标识是否第一行
            boolean isFirstRow = true;
            while (rst.next()) {
                rowCount++;     //总行数加一
                //查询全部,或者取分页范围内的记录
                if (findAll || (rowCount > fromRow && rowCount <= toRow)) {
                    ResultSetMetaData metaData = rst.getMetaData();
                    //获取列数
                    int colCount = metaData.getColumnCount();
                    //单行数据容器
                    StringBuilder rowsb = new StringBuilder();
                    rowsb.append("{");
                    //标识是否第一列
                    boolean isFirstCol = true;
                    for (int coli = 1; coli <= colCount; coli++) {
                        //获取列名
                        String colName = metaData.getColumnName(coli);
                        //获取列值
                        Object colValue = rst.getObject(coli);
                        if (colValue == null) colValue = "";
                        //如果传了显示的字段,过滤不包含的字段
                        if (fields != null && !fields.isEmpty() && fields.indexOf("," + colName + ",") < 0) {
                            continue;
                        }
                        if (isFirstCol) {
                            rowsb.append("\"" + colName + "\":");
                            rowsb.append("\"" + JsonHelper.DealForJsonString(colValue.toString()).toString() + "\"");
                            isFirstCol = false;
                        } else {
                            rowsb.append(",");
                            rowsb.append("\"" + colName + "\":");
                            rowsb.append("\"" + JsonHelper.DealForJsonString(colValue.toString()).toString() + "\"");
                        }
                    }
                    rowsb.append("}");
                    if (isFirstRow) {
                        rowAllsb.append(rowsb.toString());
                        isFirstRow = false;
                    } else {
                        rowAllsb.append(",");
                        rowAllsb.append(rowsb.toString());
                    }
                }
            }
        } catch (Exception ex) {
            //查询异常清空数据记录容器
            rowAllsb.delete(0, rowAllsb.length());
        }
        //操作结束释放资源,但是不断连接,不然没法连续做其他数据库操作了
        finally {
            if (rst != null) {
                rst.close();
            }
            if (pstat != null) {
                pstat.close();
            }
            //如果上层调用未开启事务,则调用结束释放数据库连接
            if (!Manager().Hastransaction) {
                manager.Close();
            }
        }
        //组装数据记录
        jsonsb.append(rowAllsb.toString());
        //补充数组结尾符
        jsonsb.append("]");
        if (returnCount) {
            jsonsb.append(",");
            jsonsb.append("\"total\":");
            jsonsb.append(rowCount);
            jsonsb.append("}");
        }
        return jsonsb.toString();
    }

    /**
     * 根据条件+字段查询,查询结果按指定的页面把数据按JSON返回;
     *
     * @param modelName   实体名称
     * @param param       查询条件参数,数据列名和值的键对
     * @param orderFields 排序字段,如RowID Desc
     * @param returnCount 是否输出数据总行数
     * @param pageSize    页大小。为-1,无条件查所有数据
     * @param pageIndex   第几页。为-1,无条件查询所有数据
     * @param fields      显示字段,为空显示所有列,字段名称以英文','隔开,如:RowID,Code,Name
     * @param joiner      连接符,为空或不给则查询条件以且连接,给的话长度比参数少1
     * @param operators   操作符,为空或不给的话条件以等来判断,给的话与参数长度一致。如!=,<,>
     * @return 查询json串
     */
    @Override
    public String QueryAll(String modelName, HashParam param, String orderFields, boolean returnCount, int pageSize, int pageIndex, String fields, List<String> joiner, List<String> operators) throws Exception {
        List<ParamDto> pdto = null;
        if (param != null) {
            pdto = param.GetParam();
        }
        return QueryAll(modelName, pdto, orderFields, returnCount, pageSize, pageIndex, fields, joiner, operators);
    }

    /**
     * 根据条件+字段查询,查询结果按指定的页面把数据按JSON返回;
     *
     * @param modelName   实体名称
     * @param param       查询条件参数,数据列名和值的键对
     * @param orderFields 排序字段,如RowID Desc
     * @param returnCount 是否输出数据总行数
     * @param pageSize    页大小。为-1,无条件查所有数据
     * @param pageIndex   第几页。为-1,无条件查询所有数据
     * @param fields      显示字段,为空显示所有列,字段名称以英文','隔开,如:RowID,Code,Name
     * @param joiner      连接符,为空或不给则查询条件以且连接,给的话长度比参数少1
     * @param operators   操作符,为空或不给的话条件以等来判断,给的话与参数长度一致。如!=,<,>
     * @return 查询json串
     */
    @Override
    public String QueryAll(String modelName, List<ParamDto> param, String orderFields, boolean returnCount, int pageSize, int pageIndex, String fields, List<String> joiner, List<String> operators) throws Exception {
        try {
            Class c = GetTypeByName(modelName);
            if (c != null) {
                Object o = c.getConstructor().newInstance();
                return QueryAll(o, param, orderFields, returnCount, pageSize, pageIndex, fields, joiner, operators);
            }
        } catch (Exception ex) {
            LIS.Core.Util.LogUtils.WriteExceptionLog("调用ORM的QueryAllByName异常", ex);
        }
        return "";
    }

    /**
     * 根据条件+字段查询,查询结果按指定的页面把数据按JSON返回;
     * 不分页
     *
     * @param modelName   实体名称
     * @param param       查询条件参数,数据列名和值的键对
     * @param orderFields 排序字段,如RowID Desc
     * @param returnCount 是否输出数据总行数
     * @param fields      显示字段,为空显示所有列,字段名称以英文','隔开,如:RowID,Code,Name
     * @param joiner      连接符,为空或不给则查询条件以且连接,给的话长度比参数少1
     * @param operators   操作符,为空或不给的话条件以等来判断,给的话与参数长度一致。如!=,<,>
     * @return 查询json串
     */
    @Override
    public String QueryAll(String modelName, HashParam param, String orderFields, boolean returnCount, String fields, List<String> joiner, List<String> operators) throws Exception {
        List<ParamDto> pdto = null;
        if (param != null) {
            pdto = param.GetParam();
        }
        return QueryAll(modelName, pdto, orderFields, returnCount, fields, joiner, operators);
    }

    /**
     * 根据条件+字段查询,查询结果按指定的页面把数据按JSON返回;
     * 不分页
     *
     * @param modelName   实体名称
     * @param param       查询条件参数,数据列名和值的键对
     * @param orderFields 排序字段,如RowID Desc
     * @param returnCount 是否输出数据总行数
     * @param fields      显示字段,为空显示所有列,字段名称以英文','隔开,如:RowID,Code,Name
     * @param joiner      连接符,为空或不给则查询条件以且连接,给的话长度比参数少1
     * @param operators   操作符,为空或不给的话条件以等来判断,给的话与参数长度一致。如!=,<,>
     * @return 查询json串
     */
    @Override
    public String QueryAll(String modelName, List<ParamDto> param, String orderFields, boolean returnCount, String fields, List<String> joiner, List<String> operators) throws Exception {
        try {
            Type type = GetTypeByName(modelName);
            if (type != null) {
                Object o = type.getClass().getConstructor().newInstance();
                return QueryAll(o, param, orderFields, returnCount, -1, -1, fields, joiner, operators);
            }
        } catch (Exception ex) {
            LIS.Core.Util.LogUtils.WriteExceptionLog("调用ORM的QueryAll异常", ex);
        }
        return "";
    }


    /**
     * 根据条件+字段查询,查询结果按指定的页面把数据按JSON返回;
     *
     * @param model       实体对象
     * @param param       查询条件参数,数据列名和值的键对
     * @param orderFields 排序字段,如RowID Desc
     * @param returnCount 是否输出数据总行数
     * @param pageSize    页大小。为-1,无条件查所有数据
     * @param pageIndex   第几页。为-1,无条件查询所有数据
     * @param fields      显示字段,为空显示所有列,字段名称以英文','隔开,如:RowID,Code,Name
     * @param joiner      连接符,为空或不给则查询条件以且连接,给的话长度比参数少1
     * @param operators   操作符,为空或不给的话条件以等来判断,给的话与参数长度一致。如!=,<,>
     * @param <T>         限定实体类型
     * @return 查询json串
     */
    @Override
    public <T> String QueryAll(T model, HashParam param, String orderFields, boolean returnCount, int pageSize, int pageIndex, String fields, List<String> joiner, List<String> operators) throws Exception {
        List<ParamDto> pdto = null;
        if (param != null) {
            pdto = param.GetParam();
        }
        return QueryAll(model, pdto, orderFields, returnCount, pageSize, pageIndex, fields, joiner, operators);
    }

    /**
     * 根据条件+字段查询,查询结果按指定的页面把数据按JSON返回;
     * 该方法不带分页
     *
     * @param model       实体对象
     * @param param       查询条件参数,数据列名和值的键对
     * @param orderFields 排序字段,如RowID Desc
     * @param returnCount 是否输出数据总行数
     * @param fields      显示字段,为空显示所有列,字段名称以英文','隔开,如:RowID,Code,Name
     * @param joiner      连接符,为空或不给则查询条件以且连接,给的话长度比参数少1
     * @param operators   操作符,为空或不给的话条件以等来判断,给的话与参数长度一致。如!=,<,>
     * @param <T>         限定实体类型
     * @return 查询json串
     */
    @Override
    public <T> String QueryAll(T model, HashParam param, String orderFields, boolean returnCount, String fields, List<String> joiner, List<String> operators) throws Exception {
        List<ParamDto> pdto = null;
        if (param != null) {
            pdto = param.GetParam();
        }
        return QueryAll(model, pdto, orderFields, returnCount, fields, joiner, operators);
    }

    /**
     * 根据条件+字段查询,查询结果按指定的页面把数据按JSON返回;
     * 该方法不带分页
     *
     * @param model       实体对象
     * @param param       查询条件参数,数据列名和值的键对
     * @param orderFields 排序字段,如RowID Desc
     * @param returnCount 是否输出数据总行数
     * @param fields      显示字段,为空显示所有列,字段名称以英文','隔开,如:RowID,Code,Name
     * @param joiner      连接符,为空或不给则查询条件以且连接,给的话长度比参数少1
     * @param operators   操作符,为空或不给的话条件以等来判断,给的话与参数长度一致。如!=,<,>
     * @param <T>         限定实体类型
     * @return 查询json串
     */
    @Override
    public <T> String QueryAll(T model, List<ParamDto> param, String orderFields, boolean returnCount, String fields, List<String> joiner, List<String> operators) throws Exception {
        return QueryAll(model, param, orderFields, returnCount, -1, -1, fields, joiner, operators);
    }

    /**
     * 根据条件+字段查询,查询结果按指定的页面把数据按JSON返回;
     *
     * @param model       实体对象
     * @param param       查询条件参数,数据列名和值的键对
     * @param orderFields 排序字段,如RowID Desc
     * @param returnCount 是否输出数据总行数
     * @param pageSize    页大小。为-1,无条件查所有数据
     * @param pageIndex   第几页。为-1,无条件查询所有数据
     * @param fields      显示字段,为空显示所有列,字段名称以英文','隔开,如:RowID,Code,Name
     * @param joiner      连接符,为空或不给则查询条件以且连接,给的话长度比参数少1
     * @param operators   操作符,为空或不给的话条件以等来判断,给的话与参数长度一致。如!=,<,>
     * @param <T>         限定实体类型
     * @return 查询json串
     */
    @Override
    public <T> String QueryAll(T model, List<ParamDto> param, String orderFields, boolean returnCount, int pageSize, int pageIndex, String fields, List<String> joiner, List<String> operators) throws Exception {
        //json数据组装容器
        StringBuilder jsonsb = new StringBuilder();
        //查询起始行数
        int fromRow = -1;
        //查询结束行数
        int toRow = -1;
        //是否查询全部数据
        boolean findAll = false;
        //记录总行数
        int rowCount = 0;
        //处理显示字段
        if (fields != null && !fields.isEmpty()) {
            fields = "," + fields + ",";
        }
        //如果未传入分页数据其中一个未-1,则认为部分页而查询所有数据
        if (pageIndex == -1 || pageSize == -1) {
            findAll = true;
        }
        //计算查询起始和结束行数
        else {
            fromRow = (pageIndex - 1) * pageSize;
            toRow = pageIndex * pageSize;
        }
        PreparedStatement pstat = null;
        ResultSet rst = null;
        LIS.DAL.ORM.Common.TableInfo tableInfo = LIS.DAL.ORM.Common.ModelToSqlUtil.GetTypeInfo(model);
        //根据表信息将查询参数组装成Select SQL
        String sql = LIS.DAL.ORM.Common.ModelToSqlUtil.GetSelectSqlByTableInfo(Manager().GetIDbFactory(factoryName), tableInfo, param, operators, joiner, orderFields, false);
        //写SQL日志
        LIS.Core.Util.LogUtils.WriteSqlLog("执行QueryAll返回String查询SQL:" + sql);
        //如果返回总行数,返回总行数写法
        if (returnCount) {
            jsonsb.append("{");
            jsonsb.append("\"rows\":[");
        }
        //否则采用普通数组写法
        else {
            jsonsb.append("[");
        }
        StringBuilder rowAllsb = new StringBuilder();
        try {
            pstat = Manager().Connection().prepareStatement(sql);
            String paraSql = DBParaUtil.SetDBPara(pstat, param);
            rst = pstat.executeQuery();
            LIS.Core.Util.LogUtils.WriteSqlLog("参数:" + paraSql);
            //标识是否第一行
            boolean isFirstRow = true;
            while (rst.next()) {
                rowCount++;     //总行数加一
                //查询全部,或者取分页范围内的记录
                if (findAll || (rowCount > fromRow && rowCount <= toRow)) {
                    ResultSetMetaData metaData = rst.getMetaData();
                    //获取列数
                    int colCount = metaData.getColumnCount();
                    //单行数据容器
                    StringBuilder rowsb = new StringBuilder();
                    rowsb.append("{");
                    //标识是否第一列
                    boolean isFirstCol = true;
                    for (int coli = 1; coli <= colCount; coli++) {
                        //获取列名
                        String colName = metaData.getColumnName(coli);
                        //获取列值
                        Object colValue = rst.getObject(coli);
                        if (colValue == null) colValue = "";
                        //如果传了显示的字段,过滤不包含的字段
                        if (fields != null && !fields.isEmpty() && fields.indexOf("," + colName + ",") < 0) {
                            continue;
                        }
                        if (isFirstCol) {
                            rowsb.append("\"" + colName + "\":");
                            rowsb.append("\"" + colValue + "\"");
                            isFirstCol = false;
                        } else {
                            //非第一列插入","
                            rowsb.append(",");
                            rowsb.append("\"" + colName + "\":");
                            rowsb.append("\"" + colValue + "\"");
                        }
                    }
                    rowsb.append("}");
                    if (isFirstRow) {
                        rowAllsb.append(rowsb.toString());
                        isFirstRow = false;
                    } else {
                        rowAllsb.append(",");
                        rowAllsb.append(rowsb.toString());
                    }
                }
            }
        } catch (Exception ex) {
            //查询异常清空数据记录容器
            rowAllsb.delete(0, rowAllsb.length());
        }
        //操作结束释放资源,但是不断连接,不然没法连续做其他数据库操作了
        finally {
            if (rst != null) {
                rst.close();
            }
            if (pstat != null) {
                pstat.close();
            }
            //如果上层调用未开启事务,则调用结束释放数据库连接
            if (!Manager().Hastransaction) {
                manager.Close();
            }
        }
        //组装数据记录
        jsonsb.append(rowAllsb.toString());
        //补充数组结尾符
        jsonsb.append("]");
        if (returnCount) {
            jsonsb.append(",");
            jsonsb.append("\"total\":");
            jsonsb.append(rowCount);
            jsonsb.append("}");
        }
        return jsonsb.toString();
    }

    /**
     * 根据条件+字段查询,查询结果按指定的页面把数据按JSON返回;
     *
     * @param model       实体对象
     * @param param       查询条件参数,数据列和值的键对
     * @param orderField  排序字段,如RowID Desc
     * @param returnCount 是否输出数据总行数
     * @param pageSize    页大小。为-1,无条件查所有数据
     * @param pageIndex   第几页。为-1,无条件查询所有数据
     * @param fields      显示字段,为空显示所有列,字段名称以英文','隔开,如:RowID,Code,Name
     * @param <T>         限定实体类型
     * @return 查询数据json串
     */
    public <T> String SelectAll(T model, HashParam param, String orderField, boolean returnCount, int pageSize, int pageIndex, String fields) throws Exception {
        return QueryAll(model, param, orderField, returnCount, pageSize, pageIndex, fields, null, null);
    }

    /**
     * 根据条件+字段查询,查询结果按指定的页面把数据按JSON返回;
     * 不分页
     *
     * @param modelName   实体名称
     * @param param       查询条件参数,数据列名和值的键对
     * @param orderFields 排序字段,如RowID Desc
     * @param fields      显示字段,为空显示所有列,字段名称以英文','隔开,如:RowID,Code,Name
     * @param joiner      连接符,为空或不给则查询条件以且连接,给的话长度比参数少1
     * @param operators   操作符,为空或不给的话条件以等来判断,给的话与参数长度一致。如!=,<,>
     * @param <T>         限定实体类型
     * @return 查询实体列表List<T>
     */
    @Override
    public <T> List<T> QueryAll(String modelName, HashParam param, String orderFields, String fields, List<String> joiner, List<String> operators) throws Exception {
        List<ParamDto> pdto = new LinkedList<>();
        if (param != null) {
            pdto = param.GetParam();
        }
        return QueryAll(modelName, pdto, orderFields, fields, joiner, operators);
    }

    /**
     * 根据条件+字段查询,查询结果按指定的页面把数据按JSON返回;
     * 不分页
     *
     * @param modelName   实体名称
     * @param param       查询条件参数,数据列名和值的键对
     * @param orderFields 排序字段,如RowID Desc
     * @param fields      显示字段,为空显示所有列,字段名称以英文','隔开,如:RowID,Code,Name
     * @param joiner      连接符,为空或不给则查询条件以且连接,给的话长度比参数少1
     * @param operators   操作符,为空或不给的话条件以等来判断,给的话与参数长度一致。如!=,<,>
     * @param <T>         限定实体类型
     * @return 查询实体列表List<T>
     */
    @Override
    public <T> List<T> QueryAll(String modelName, List<ParamDto> param, String orderFields, String fields, List<String> joiner, List<String> operators) throws Exception {
        List<T> list = new ArrayList<T>();
        try {
            Type type = GetTypeByName(modelName);
            if (type != null) {
                T model = (T) type.getClass().getConstructor().newInstance();
                return QueryAll(model, param, orderFields, fields, joiner, operators);
            }
        } catch (Exception ex) {

        }
        return list;
    }

    /**
     * 根据条件+字段查询,查询结果按指定的页面把数据按JSON返回;
     * 不分页
     *
     * @param model       实体对象
     * @param param       查询条件参数,数据列名和值的键对
     * @param orderFields 排序字段,如RowID Desc
     * @param fields      显示字段,为空显示所有列,字段名称以英文','隔开,如:RowID,Code,Name
     * @param joiner      连接符,为空或不给则查询条件以且连接,给的话长度比参数少1
     * @param operators   操作符,为空或不给的话条件以等来判断,给的话与参数长度一致。如!=,<,>
     * @param <T>         限定实体类型
     * @return 查询实体列表List<T>
     */
    @Override
    public <T> List<T> QueryAll(T model, HashParam param, String orderFields, String fields, List<String> joiner, List<String> operators) throws Exception {
        List<ParamDto> pdto = null;
        if (param != null) {
            pdto = param.GetParam();
        }
        return QueryAll(model, pdto, orderFields, fields, joiner, operators);
    }

    /**
     * 根据条件+字段查询,查询结果按指定的页面把数据按JSON返回;
     * 不分页
     *
     * @param model       实体对象
     * @param param       查询条件参数,数据列名和值的键对
     * @param orderFields 排序字段,如RowID Desc
     * @param fields      显示字段,为空显示所有列,字段名称以英文','隔开,如:RowID,Code,Name
     * @param joiner      连接符,为空或不给则查询条件以且连接,给的话长度比参数少1
     * @param operators   操作符,为空或不给的话条件以等来判断,给的话与参数长度一致。如!=,<,>
     * @param <T>         限定实体类型
     * @return 查询实体列表List<T>
     */
    @Override
    public <T> List<T> QueryAll(T model, List<ParamDto> param, String orderFields, String fields, List<String> joiner, List<String> operators) throws Exception {
        return QueryAll(model, param, orderFields, -1, -1, fields, joiner, operators);
    }

    /**
     * 根据条件+字段查询,查询结果按指定的页面把数据按JSON返回;
     *
     * @param model       实体对象
     * @param param       查询条件参数,数据列名和值的键对
     * @param orderFields 排序字段,如RowID Desc
     * @param pageSize    页大小。为-1,无条件查所有数据
     * @param pageIndex   第几页。为-1,无条件查询所有数据
     * @param fields      显示字段,为空显示所有列,字段名称以英文','隔开,如:RowID,Code,Name
     * @param joiner      连接符,为空或不给则查询条件以且连接,给的话长度比参数少1
     * @param operators   操作符,为空或不给的话条件以等来判断,给的话与参数长度一致。如!=,<,>
     * @param <T>         限定实体类型
     * @return 查询实体列表List<T>
     */
    @Override
    public <T> List<T> QueryAll(T model, HashParam param, String orderFields, int pageSize, int pageIndex, String fields, List<String> joiner, List<String> operators) throws Exception {
        List<ParamDto> pdto = null;
        if (param != null) {
            pdto = param.GetParam();
        }
        return QueryAll(model, pdto, orderFields, pageSize, pageIndex, fields, joiner, operators);
    }

    /**
     * 根据条件+字段查询,查询结果按指定的页面把数据按JSON返回;
     *
     * @param model       实体对象
     * @param param       查询条件参数,数据列名和值的键对
     * @param orderFields 排序字段,如RowID Desc
     * @param pageSize    页大小。为-1,无条件查所有数据
     * @param pageIndex   第几页。为-1,无条件查询所有数据
     * @param fields      显示字段,为空显示所有列,字段名称以英文','隔开,如:RowID,Code,Name
     * @param joiner      连接符,为空或不给则查询条件以且连接,给的话长度比参数少1
     * @param operators   操作符,为空或不给的话条件以等来判断,给的话与参数长度一致。如!=,<,>
     * @param <T>         限定实体类型
     * @return 查询实体列表List<T>
     */
    @Override
    public <T> List<T> QueryAll(T model, List<ParamDto> param, String orderFields, int pageSize, int pageIndex, String fields, List<String> joiner, List<String> operators) throws Exception {
        //存储返回的对象数据
        List<T> retList = new ArrayList<T>();
        //查询起始行数
        int fromRow = -1;
        //查询结束行数
        int toRow = -1;
        //是否查询全部数据
        boolean findAll = false;
        //记录总行数
        int rowCount = 0;
        //处理显示字段
        if (fields != null && !fields.isEmpty()) {
            fields = "," + fields + ",";
        }
        //如果未传入分页数据其中一个未-1,则认为部分页而查询所有数据
        if (pageIndex == -1 || pageSize == -1) {
            findAll = true;
        }
        //计算查询起始和结束行数
        else {
            fromRow = (pageIndex - 1) * pageSize;
            toRow = pageIndex * pageSize;
        }
        PreparedStatement pstat = null;
        ResultSet rst = null;
        LIS.DAL.ORM.Common.TableInfo tableInfo = LIS.DAL.ORM.Common.ModelToSqlUtil.GetTypeInfo(model);
        //根据表信息将查询参数组装成Select SQL
        String sql = LIS.DAL.ORM.Common.ModelToSqlUtil.GetSelectSqlByTableInfo(Manager().GetIDbFactory(factoryName), tableInfo, param, operators, joiner, orderFields, false);
        //写SQL日志
        LIS.Core.Util.LogUtils.WriteSqlLog("执行QueryAll返回List<T>查询SQL:" + sql);
        Class<?> clazzz = model.getClass();
        try {
            pstat = Manager().Connection().prepareStatement(sql);
            String paraSql = DBParaUtil.SetDBPara(pstat, param);
            rst = pstat.executeQuery();
            LIS.Core.Util.LogUtils.WriteSqlLog("参数:" + paraSql);
            //标识是否第一行
            boolean isFirstRow = true;
            while (rst.next()) {
                rowCount++;     //总行数加一
                //查询全部,或者取分页范围内的记录
                if (findAll || (rowCount > fromRow && rowCount <= toRow)) {
                    T obj = (T) clazzz.getConstructor().newInstance();
                    for (int coli = 0; coli < tableInfo.ColList.size(); coli++) {
                        String name = tableInfo.ColList.get(coli).Name;
                        Object value = rst.getObject(name);
                        LIS.Core.Util.ReflectUtil.SetObjValue(obj, name, value);
                    }
                    retList.add(obj);
                }
            }
        } catch (Exception ex) {
            //查询异常清空数据
            retList.clear();
        }
        //操作结束释放资源,但是不断连接,不然没法连续做其他数据库操作了
        finally {
            if (rst != null) {
                rst.close();
            }
            if (pstat != null) {
                pstat.close();
            }
            //如果上层调用未开启事务,则调用结束释放数据库连接
            if (!Manager().Hastransaction) {
                manager.Close();
            }
        }
        return retList;
    }

    /**
     * 数据查询
     *
     * @param model       实体对象
     * @param param       查询条件参数,数据列名和值的键对
     * @param orderFields 排序字段,如RowID Desc
     * @param pageSize    页大小。为-1,无条件查所有数据
     * @param pageIndex   第几页。为-1,无条件查询所有数据
     * @param <T>         限定实体类型
     * @return 实体对象列表
     */
    public <T> List<T> FindAll(T model, HashParam param, String orderFields, int pageSize, int pageIndex) throws Exception {
        return QueryAll(model, param, orderFields, pageSize, pageIndex, "", null, null);
    }

    /**
     * 通过实体名称得到实体信息
     *
     * @param modelName 实体名称
     * @return 实体信息json串
     */
    @Override
    public String GetModelInfoByName(String modelName) throws Exception {
        //返回表消息容器
        StringBuilder tableInfoJson = new StringBuilder();
        //先获取类对象,实例化实体对象
        Class<?> clazz = Class.forName("LIS.Model.Entity." + modelName);
        LIS.DAL.ORM.Common.TableInfo tableInfo = LIS.DAL.ORM.Common.ModelToSqlUtil.GetTypeInfo(clazz.getConstructor().newInstance());
        if (tableInfo != null) {
            //表名
            String tableName = tableInfo.TableInfo.Name();
            tableInfoJson.append("{\"tableName\":\"" + tableName + "\",\"columns\":[");
            //列信息
            List<LIS.DAL.ORM.Common.ColumnInfo> colInfo = tableInfo.ColList;
            //ID信息
            LIS.DAL.ORM.Common.IdInfo idInfo = tableInfo.ID;
            String idName = idInfo.Key;
            boolean isFirst = true;
            //处理列信息
            for (int coli = 0; coli < colInfo.size(); coli++) {
                LIS.DAL.ORM.Common.ColumnInfo col = colInfo.get(coli);
                String colName = col.Name;
                if (isFirst) {
                    tableInfoJson.append("{\"columnName\":\"" + colName + "\"");
                    isFirst = false;
                } else {
                    tableInfoJson.append(",");
                    tableInfoJson.append("{\"columnName\":\"" + colName + "\"");
                }
                //是否ID字段
                if (idName.equals(colName)) {
                    tableInfoJson.append(",\"isId\":true");
                } else {
                    tableInfoJson.append(",\"isId\":false");
                }
                //外键特性
                FrekeyAttribute frekeys = col.FkInfo;
                if (frekeys != null) {
                    tableInfoJson.append(",\"fkModelName\":\"" + frekeys.Name() + "\",\"refColumnName\":\"" + frekeys.RefColumnName() + "\",\"AssociaField\":\"" + frekeys.AssociaField() + "\"");
                }
                tableInfoJson.append("}");
            }
            tableInfoJson.append("]}");
        }
        return tableInfoJson.toString();
    }

    /**
     * 通过实体名称获得实体类型信息
     *
     * @param modelName 实体名称
     * @return
     */
    public Class GetTypeByName(String modelName) throws Exception {
        return LIS.Core.Util.ReflectUtil.GetType("LIS.Model.Entity." + modelName, "LIS.Model");
    }

}

实现配置获取类
在这里插入图片描述

package LIS.Core.MultiPlatform;

import java.io.File;
import java.net.URL;
import java.nio.file.Paths;
import java.util.Hashtable;

import LIS.Core.MultiPlatform.LISContext;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

/**
 * 获得配置工具
 */
public class LISConfigurtaion {

    /**
     * 存解析的参数
     */
    private static Hashtable<String, String> hs = new Hashtable();

    /**
     * 是否初始化
     */
    private static boolean hasInit = false;

    /**
     * 按键取值
     *
     * @param key 键
     * @return
     * @throws Exception
     */
    public static String Configuration(String key) throws Exception {
        if (hasInit == false) {
            Init();
        }
        if (hs.containsKey(key)) {
            return hs.get(key);
        }
        return "";
    }

    /**
     * 初始化配置获取
     *
     * @throws Exception
     */
    public static void Init() throws Exception {
        String confPath = Paths.get(LISContext.WebBasePath, "Conf", "appsetting.xml").toString();
        //判断配置是否存在
        File file = new File(confPath);
        if (!file.exists()) {
            throw new Exception(confPath + "文件不存在,请确认!");
        }
        //解析xml
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        Document document = builder.parse(file);
        // 获得根节点
        Element rootElement = document.getDocumentElement();
        // 获得根节点下的所有子节点
        NodeList students = rootElement.getChildNodes();
        for (int i = 0; i < students.getLength(); i++) {
            // 由于节点多种类型,而一般我们需要处理的是元素节点
            Node childNode = students.item(i);
            // 元素节点就是非空的子节点,也就是还有孩子的子节点
            if (childNode.getNodeType() == Node.ELEMENT_NODE) {
                Element childElement = (Element) childNode;
                //不是对象配置元素就忽略
                if (childElement.getNodeName() != "add") {
                    continue;
                }
                //解析类型配置
                String key = childElement.getAttribute("key");
                //是否单例
                String value = childElement.getAttribute("value");
                hs.put(key, value);
            }
        }
    }
}

修改数据库驱动实现类

package LIS.Dal.Base;

import LIS.DAL.ORM.DBUtility.IDbFactory;
import LIS.Core.MultiPlatform.LISConfigurtaion;
import LIS.Core.Util.Convert;

import java.sql.*;

/**
 * postgresql驱动实现类
 */
public class PostgreSqlBase implements LIS.DAL.ORM.DBUtility.IDbFactory {
    /**
     * 得到数据库类型
     *
     * @return
     */
    public String GetStrDbType() {
        return "pgsql";
    }

    /**
     * 得到数据库连接串,先写死,后面从配置取
     *
     * @return
     */
    public String GetConnectionString() throws Exception {
        return LISConfigurtaion.Configuration("ConnectionString");
    }

    /**
     * 得到数据库用户名
     *
     * @return
     */
    public String GetUserName() throws Exception {
        return LISConfigurtaion.Configuration("UserName");
    }

    /**
     * 得到数据库密码
     *
     * @return
     */
    public String GetUserPass() throws Exception {
        return LISConfigurtaion.Configuration("UserPass");
    }

    /**
     * 得到返回查询的RowID的SQL语句,供插入数据得到RowID用
     *
     * @return
     */
    public String GetReturnRowIDSql() {
        return " RETURNING \"RowID\"";
    }

    /**
     * 处理表名称,用来适配不同数据库间的属性命名差异
     *
     * @param tableName 表名
     * @return
     */
    public String DealTableName(String tableName) {
        return tableName;
    }

    /**
     * 处理属性名字
     *
     * @param propertyName 属性名字
     * @return
     */
    public String DealPropertyName(String propertyName) {
        return "\"" + propertyName + "\"";
    }

    /**
     * 处理Sql参数
     *
     * @param propertyName 属性名字
     * @return
     */
    public String DealSqlPara(String propertyName) {
        return "?";
    }

    /**
     * 加载驱动
     *
     * @return
     */
    public String GetDriver() {
        return "org.postgresql.Driver";
    }

    /**
     * 得到初始化连接串大小
     *
     * @return
     */
    public int GetInitPoolSize() throws Exception {
        String initSize = LISConfigurtaion.Configuration("PoolInitPoolSize");
        return Convert.ToInt32(initSize);
    }

    /**
     * 得到最大连接串大小
     *
     * @return
     */
    public int GetMaxPoolSize() throws Exception {
        String maxSize = LISConfigurtaion.Configuration("PoolMaxPoolSize");
        return Convert.ToInt32(maxSize);
    }

}

配置数据库连接
在这里插入图片描述
连本地库测试
在这里插入图片描述
多开刷新测连接
在这里插入图片描述

本次涉及连接池、不同数据库接口定义、读取连接串配置、管理连接和事务、写Sql日志

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/134103.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【网络奇遇记】你真的了解网络中的电路交换、分组交换和报文交换吗?

&#x1f308;个人主页&#xff1a;聆风吟 &#x1f525;系列专栏&#xff1a;网络奇遇记、数据结构 &#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 文章目录 一. 电路交换1.1 电路交换讲解1.2 电路交换实例 二. 分组交换1.1 分组交换讲解1.2 分组交换实例1.3 …

Flutter 实战:构建跨平台应用

文章目录 一、简介二、开发环境搭建三、实战案例&#xff1a;开发一个简单的天气应用1. 项目创建2. 界面设计3. 数据获取4. 实现数据获取和处理5. 界面展示6. 添加动态效果和交互7. 添加网络错误处理8. 添加刷新功能9. 添加定位功能10. 添加通知功能11. 添加数据持久化功能 《F…

CSS的初步学习

CSS 层叠样式表 (Cascading Style Sheets). CSS 能够对网页中元素位置的排版进行像素级精确控制, 实现美化页面的效果. 能够做到页面的样式和结 构分离. CSS 就是 “东方四大邪术” 之化妆术 CSS 基本语法规范: 选择器 若干属性声明 选择器决定针对谁修改 (找谁) 声明决定修…

有没有实时检测微信聊天图片的软件,只要微信收到了有二维码的图片就把它提取出来?

10-2 如果你有需要自动并且快速地把微信收到的二维码图片保存到指定文件夹的需求&#xff0c;那本文章非常适合你&#xff0c;本文章教你如何实现自动保存微信收到的二维码图片到你指定的文件夹中&#xff0c;助你快速扫码&#xff0c;比别人领先一步。 首先需要准备好的材料…

Spark的执行计划

Spark 3.0 大版本发布&#xff0c;Spark SQL 的优化占比将近 50%。Spark SQL 取代 Spark Core&#xff0c;成为新一代的引擎内核&#xff0c;所有其他子框架如 Mllib、Streaming 和 Graph&#xff0c;都可以共享 Spark SQL 的性能优化&#xff0c;都能从 Spark 社区对于 Spark …

计算机毕业设计 基于SpringBoot的驾校管理系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

nodejs+vue+python+PHP+微信小程序-安卓- 基于小程序的高校后勤管理系统-计算机毕业设计

目 录 摘 要 I ABSTRACT II 目 录 II 第1章 绪论 1 1.1背景及意义 1 1.2 国内外研究概况 1 1.3 研究的内容 1 第2章 相关技术 3 2.1 nodejs简介 4 2.2 express框架介绍 6 2.4 MySQL数据库 4 第3章 系统分析 5 3.1 需求分析 5 3.2 系统可行性分析 5 3.2.1技术可行性&#xff1a;…

C/C++数字判断 2021年9月电子学会青少年软件编程(C/C++)等级考试一级真题答案解析

目录 C/C数字判断 一、题目要求 1、编程实现 2、输入输出 二、算法分析 三、程序编写 四、程序说明 五、运行结果 六、考点分析 C/C数字判断 2021年9月 C/C编程等级考试一级编程题 一、题目要求 1、编程实现 输入一个字符&#xff0c;如何输入的字符是数字&#x…

Linux —— 网络编程套接字

目录 一&#xff0c;网络字节序 二&#xff0c;socket编程接口 sockaddr结构 源IP地址、目的IP地址&#xff0c;在IP数据包头部&#xff0c;有此两个IP地址&#xff1b; 端口号&#xff0c;是传输层协议的内容&#xff1b; 端口号是一个2字节16位的整数&#xff1b;端口号用…

什么是Amazon Simple Email Service(SES 群发邮件)

Amazon Simple Email Service&#xff08;Amazon SES&#xff09;让您可以使用 Amazon SES API 或 SMTP 接口放心地联络到客户&#xff0c;而无需使用本地简单邮件传输协议&#xff08;Simple Mail Transfer Protocol&#xff0c;SMTP&#xff09;电子邮件服务器。 目录 什么是…

C++学习---信号处理机制、中断、异步环境

文章目录 前言信号处理signal()函数关于异步环境 信号处理函数示例raise()函数 前言 信号处理 关于信号&#xff0c;信号是一种进程间通信的机制&#xff0c;用于在程序执行过程中通知进程发生了一些事件。在Unix和类Unix系统中&#xff0c;信号是一种异步通知机制&#xff0c…

代码随想录 Day43 动态规划11 LeetCode T309 买卖股票的最佳时期含冷冻期 T714买卖股票的最佳时机含手续费

LeetCode T309 买卖股票的最佳时机含冷冻期 题目链接:309. 买卖股票的最佳时机含冷冻期 - 力扣&#xff08;LeetCode&#xff09; 题目思路: 这题其实就是将卖出的状态拆分成三个状态 1.前两天就卖出并一直保持卖出的状态 2.今天卖出的状态 3.今天是冷冻期的状态 当然还有一个…

最新支付宝转卡码生成之转账源代码(隐藏部分卡号)

一、需要准备好自己的卡号、名称、以及对应的姓名 二、然后将自己的信息填入下面的代码中 三、然后将拼接好的代码&#xff0c;利用转码技术生产对应的二维码 四、这样一个跳转银行卡二维码的转账码就做好了 效果演示&#xff1a;如下 支付宝扫码、跳转码、转卡码、隐藏卡号…

【刷题】力扣每日一题 : 381、2300、765

前言 本篇文章用于记录在做力扣每日一题的时候遇到的一些知识点以及自己的思路 381 题干 题目链接 我的思路及做题过程 思路1 我的想法是 记录每个字符串的字母出现个数 然后比较两个字符串是否有字母同时出现 class Solution { public:int judge(string s1, string s2…

asp.net core自定义异常过滤器并记录到Log4Net日志

1.创建异常过滤器特性 using Log4Net.Controllers; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters;namespace Log4NetTest {public class CustomerExceptionFilterAttribute : Attribute, IExceptionFilter{private readonly ILogger<CustomerE…

CSS布局001:画各种三角形

CSS实战中&#xff0c;有很多时候采用css来绘制三角形&#xff0c;而不是采用图片的方式&#xff0c;这样有利于快速成型&#xff0c;不用多调用服务器数据。 CSS代码 上三角 #triangle-up {width: 0;height: 0;border-left: 50px solid transparent;border-right: 50px solid…

idea配置tomcat参数,防止nvarchar保存韩文、俄文、日文等乱码

描述下我的场景&#xff1a; 数据库服务器在远程机器上&#xff0c;数据库使用的Oracle&#xff0c;字符集是ZHS16GBK&#xff0c;但保存韩文、俄文、日文等字段A的数据类型是nvarchar(120)&#xff0c;而nvarchar使用的是Unicode 编码&#xff0c;有点乱。。 遇到的问题&…

ArcGIS:如何迭代Shp文件所有要素并分别导出为Shp文件?

01 前言 尝试用IDL实现&#xff0c;奈何又涉及新的类IDLffShape&#xff0c;觉得实在没有必要学习的必要&#xff0c;毕竟不是搞开发&#xff0c;只是做做数据处理&#xff0c;没必要拿IDL不擅长的且底层的东西自己造轮子。 这里想到使用Python去解决&#xff0c;gdal太久没用…

微信的聊天记录导出到网页中的最快方法,语音能听,图片视频能看

12-7 如果你有把微信的聊天记录导出到表格或者网页上的需求&#xff0c;适合看看本文章&#xff0c;本文的方法可以让你把微信的聊天记录导出备份&#xff0c;可以在完全脱离微信的情况下随时调取查看聊天数据。 本文介绍的软件可以导出两种格式的聊天记录备份文件&#xff0…

【C语言】冒泡排序(图解)

&#x1f308;write in front :&#x1f50d;个人主页 &#xff1a; 啊森要自信的主页 &#x1f308;作者寄语 &#x1f308;&#xff1a; 小菜鸟的力量不在于它的体型&#xff0c;而在于它内心的勇气和无限的潜能&#xff0c;只要你有决心&#xff0c;就没有什么事情是不可能的…
最新文章