jbase引入连接池

news2024/11/18 20:29:28

网站主题和代码生成器完事之后,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.coloradmin.cn/o/1196441.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Maven打包引入本地依赖包

Maven打包引入本地依赖包 SpringBoot 工程&#xff0c;Maven 在构建项目时&#xff0c;如何引入本地 Jar 包&#xff1f; 适合场景&#xff1a; 引用的依赖不在 Maven 仓库第三方公司提供的 SDK 包Maven 内网离线开发引入被定制改动过的 Jar 包 解决方法&#xff1a; 在 I…

nature日报:为什么印度德里现在的空气污染如此严重?

为什么印度德里现在的空气污染如此严重&#xff1f; 后季风季节为印度大城市的空气污染积累创造了理想的条件。 本文整理扩展自2023年11月10日nature杂志的NEWS EXPLAINER——Why is Delhi’s air pollution so bad right now? (nature.com) Highlights 季风期间&#xff0…

卡码网语言基础课 | 11. 句子缩写

目录 一、 字符串大小的比较 二、 ASCII码值 三、 基本框架代码 四、 解题思路 4.1 首字母问题 4.2 判定小写字母 4.3 小写字母转换为大写字母 五、空格判断 六、 代码模块化 6.1 满足的条件 6.2 代码完善 七、 题目解答 7.1 原始代码 7.2 改进代码 八、 拓展与…

Java_继承和多态

文章目录 前言继承继承语法继承总结super指定访问父级子类构造方法super和this再谈初始化(执行顺序)protected 关键字继承方式final 关键字继承与组合 多态动态绑定与静态绑定多态实现条件重写 前言 适合复习看 继承 继承语法 修饰符 class 子类 extends 父类 { // ... }子类…

[BJDCTF2020]Easy MD5 1

题目环境&#xff1a; 尝试了SQL注入、命令执行等都不行 点击提交并burp进行抓包Repeater进行重放这里看到了内置的SQL语句select * from admin where passwordmd5($pass,true) 发现传进去的值会进行md5加密 这里看了大佬们的解释 ffifdyop绕过&#xff0c;绕过原理是&#xff…

2023最新软件测试面试300问

一、Linux系统应用和环境配置 1、Linux系统的操作命令给我说10个&#xff0c;一般用什么工具远程连接Linux服务器&#xff1f; 2、Linux中的日志存储在哪里&#xff1f;怎么查看日志内容&#xff1f; 3、Linux中top和ps命令的区别&#xff1f; 4、Linux命令运行的结果如何写…

配置cuda和cudnn出现 libcudnn.so.8 is not a symbolic link问题

cuda版本为11.2 问题如图所示&#xff1a; 解决办法&#xff1a; sudo ln -sf /usr/local/cuda-11.2/targets/x86_64-linux/lib/libcudnn_adv_train.so.8.1.1 /usr/local/cuda-11.2/targets/x86_64-linux/lib/libcudnn_adv_train.so.8 sudo ln -sf /usr/local/cuda-11.2/targ…

CKA认证模块②-K8S企业运维和落地实战-2

CKA认证模块②-K8S企业运维和落地实战-2 K8S常见的存储方案及具体应用场景分析 k8s存储-empty emptyDir类型的Volume是在Pod分配到Node上时被创建&#xff0c;Kubernetes会在Node上自动分配一个目录&#xff0c;因此无需指定宿主机Node上对应的目录文件。 这个目录的初始内容…

用volta管理不同项目node版本

1 什么是volta volta是一个node.js的版本管理工具&#xff0c;你的电脑上安装了很多个node版本&#xff0c;volta可以让你在不同的项目中使用不同版本的node.js,并且可以切换node.js版本 Volta会自动将安装的Node.js版本与该项目绑定&#xff0c;使得您在该项目中执行 node、np…

【LLM_03】自然语言处理基础_1

一、自然语言处理基基本任务和应用1、自然语言处理的基本任务2、搜索引擎的基本工作原理3、知识图谱的构建4、应用 二、词表示与语言模型1、词表示2、上下文3、语言模型4、神经网络在语言模型的应用 三、神经网络1、神经网络基本组成元素2、如何训练神经网络3、计算图的概念4、…

巨好用又实用的18款3dMax插件!

3dMax是一款功能强大的 3D 软件&#xff0c;具有建模、动画、粒子动力学等许多强大功能。但并不是每个人都能有效地利用max的每一个功能&#xff0c;例如&#xff0c;很多人发现3dmax粒子流太难使用&#xff0c;3ds max蒙皮工具也是如此。 这让我们一些专业的开发公司或个人和…

it is missing from your system. Install or enable PHP‘s sodium extension.

Composer with –ignore-platform-reqext-sodium it is missing from your system. Install or enable PHP’s sodium extension. 出现如上的报错是的 开启php.ini中的 sodium的扩展

香港云服务器用于跨境电商外贸

港作为国际金融中心和互联网枢纽&#xff0c;具有非常发达的网络基础设施和优质的网络连接。这意味着在香港租用云服务器&#xff0c;外贸企业可以享受到高速稳定的网络连接&#xff0c;确保数据传输的安全和稳定性。这对于外贸企业来说至关重要&#xff0c;因为他们需要频繁地…

istio流量管理

流量管理 目录 文章目录 流量管理目录流量管理概述请求路由1.路由到版本1&#x1f6a9; 实战&#xff1a;路由到版本1-2023.11.11(测试成功) 2.基于用户身份的路由&#x1f6a9; 实战&#xff1a;基于用户身份的路由-2023.11.11(测试成功) 关于我最后 流量管理概述 上面我们了…

14 # 手写 debounce 防抖方法

什么是防抖 防抖: n 秒后再去执行该事件&#xff0c;若在 n 秒内被重复触发&#xff0c;则重新计时&#xff0c;这个效果跟英雄联盟里的回城技能差不多。 本质上是优化高频率执行代码的一种手段&#xff0c;目的就是降低回调执行频率、节省计算资源。 应用场景&#xff1a; …

基于subversion1.6.3动态库实现简单版本管理

基于subversion1.6.3动态库实现简单版本管理 一、运行环境 windows10 64位系统 VS2015、C Subversion1.6.3 二、功能设计与实现 1、需求背景 编码自动化版本部署、发布验证&#xff1b; svn cli命令行能满足基本功能&#xff0c;但是动作执行是否成功的判断不可靠&#…

GPU CUDA 使用shared memory 运行速度不升反降原因与解决方案

写了两张图像相加&#xff0c;以及图像滤波的的几个算子&#xff0c;分别采用shared memory 进行优化。 #include <stdio.h> #include <cuda_runtime.h>#include "helper_cuda.h" #include "helper_timer.h"#define BLOCKX 32 #define BLOCKY…

【C语言 | 预处理】C语言预处理详解(三)——内存对齐、手把手带你计算结构体大小

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; &#x1f923;本文内容&#x1f923;&a…

2023年加氢工艺证考试题库及加氢工艺试题解析

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2023年加氢工艺证考试题库及加氢工艺试题解析是安全生产模拟考试一点通结合&#xff08;安监局&#xff09;特种作业人员操作证考试大纲和&#xff08;质检局&#xff09;特种设备作业人员上岗证考试大纲随机出的加氢…

DDU框架学习之路

目录 MVVM对比 DDU 数据消费者UI 数据的转换者&#xff1a;Domain Layer 数据图生产者/提供者 DataLayer 遵循原理&#xff1a; 单一数据流&#xff1a; Android官方推荐架构&#xff1a;DDU MVVM对比 M&#xff1a;Model 网络层 用于获取远端数据 VM:ViewModel 中间转…