【仿真建模-anylogic】数据源组件

Author:赵志乾
Date:2024-07-16
Declaration:All Right Reserved!!!

1. 简介

        仿真模型依赖的数据源通常有Excel文件、MySQL数据库两种;针对小数量、大数据量以及是否允许外部依赖等场景设计了一套通用数据源组件;该套数据源组件支持3种数据源:

  • 小数据量且无外部依赖:ExcelDataSource
  • 大数据量且无外部依赖:MultiExcelDataSource
  • 允许外部依赖:MySqlDataSource

        数据存取操作均通过接口IDataSource进行,依据实际场景不同,切换不同数据源实现即可;

2.  抽象数据源接口

public interface IDataSource {// taskId为一次仿真的唯一标识// containerName为数据库表名或者Sheet页名称// items为要存储的数据// clazz为数据类信息<T> void store(String taskId, String containerName, List<T> items, Class<T> clazz);<T> List<T> query(String taskId, String containerName, Class<T> clazz);
}

3. ExcelDataSource

        ExcelDataSource针对于小数据量场景,单个Excel即可存储所有数据;

public class ExcelDataSource implements IDataSource {// excel文件路径private final String path;public ExcelDataSource(String path) {this.path = path;}public ExcelDataSource() {this("");}@Overridepublic <T> void store(String taskId, String containerName, List<T> items, Class<T> clazz) {EasyExcelUtil.write(path + taskId, "data.xlsx", containerName, items, clazz);}@Overridepublic <T> List<T> query(String taskId, String containerName, Class<T> clazz) {List<T> result = new ArrayList<>();Path directoryPath = Paths.get(path + taskId);try (Stream<Path> paths = Files.list(directoryPath)) {paths.forEach(file -> {String fileName = file.getFileName().getFileName().toString();if(fileName.endsWith("xlsx")){result.addAll(EasyExcelUtil.read(path + taskId, fileName, containerName, clazz));}});} catch (IOException e) {throw new RuntimeException(e);}return result;}
}

4. MultiExcelDataSource

        MultiExcelDataSource针对大数据量而又不希望引入外部依赖的场景,其输入输出支持多Excel文件,以文件名数字后缀进行数据的切分;

public class MultiExcelDataSource implements IDataSource {private final String path;private final IDataSource excelDataSource;public MultiExcelDataSource(String path) {this.path = path;excelDataSource = new ExcelDataSource(path);}public MultiExcelDataSource() {this("");}@Overridepublic synchronized <T> void store(String taskId, String containerName, List<T> items, Class<T> clazz) {int batchSize = 1000;int fileNum = (items.size() + batchSize - 1) / batchSize;for (int index = 0; index < fileNum; index++) {List<T> subList = items.subList(index * batchSize, Math.min((index + 1) * batchSize, items.size()));EasyExcelUtil.write(path + taskId, "data" + index + ".xlsx", containerName, subList, clazz);}}@Overridepublic <T> List<T> query(String taskId, String containerName, Class<T> clazz) {return excelDataSource.query(taskId, containerName, clazz);}
}

5. MySqlDataSource 

        MySqlDataSource适用于大数量场景;

@Data
@AllArgsConstructor
public class MySqlDataSource implements IDataSource {private final String url;private final String userName;private final String password;private final static int batchSize = 500;@Overridepublic synchronized <T> void store(String taskId, String containerName, List<T> items, Class<T> clazz) {Field[] fields = clazz.getDeclaredFields();Map<String, Field> columnToFieldMap = getColumToFieldMap(fields, clazz);Connection connection = null;PreparedStatement preparedStatement = null;try {connection = DriverManager.getConnection(url, userName, password);connection.setAutoCommit(false);StringBuilder sql = new StringBuilder("INSERT INTO ");sql.append(containerName).append("(task_id,");List<String> columns = new ArrayList<>(columnToFieldMap.keySet());for (int index = 0; index < columns.size(); index++) {sql.append(columns.get(index)).append(",");}sql.setCharAt(sql.length() - 1, ')');sql.append("VALUES(?,");for (int index = 0; index < columns.size(); index++) {sql.append("?,");}sql.setCharAt(sql.length() - 1, ')');preparedStatement = connection.prepareStatement(sql.toString());int totalBatch = (items.size() + batchSize - 1) / batchSize;for (int index = 0; index < totalBatch; index++) {preparedStatement.setString(1, taskId);List<T> subList = items.subList(index * batchSize, Math.min((index + 1) * batchSize, items.size()));for (int itemIndex = 0; itemIndex < subList.size(); itemIndex++) {T item = subList.get(itemIndex);for (int columnIndex = 0; columnIndex < columns.size(); columnIndex++) {String column = columns.get(columnIndex);Field field = columnToFieldMap.get(column);Class columnClazz = field.getType();if (columnClazz == String.class) {preparedStatement.setString(columnIndex + 2, (String) field.get(item));} else if (columnClazz == Integer.class) {preparedStatement.setInt(columnIndex + 2, (Integer) field.get(item));} else if (columnClazz == Long.class) {preparedStatement.setLong(columnIndex + 2, (Long) field.get(item));} else if (columnClazz == Float.class) {preparedStatement.setFloat(columnIndex + 2, (Float) field.get(item));} else if (columnClazz == Double.class) {preparedStatement.setDouble(columnIndex + 2, (Double) field.get(item));} else if (columnClazz == DateTime.class) {preparedStatement.setTimestamp(columnIndex + 2, new Timestamp(((DateTime) field.get(item)).getMillis()));} else {throw new RuntimeException("类型不支持!type=" + field.getType().getTypeName());}}preparedStatement.addBatch();}int[] updateCounts = preparedStatement.executeBatch();for (int count : updateCounts) {if (count < 1) {throw new SQLException("数据库操作失败!");}}connection.commit();}} catch (SQLException | IllegalAccessException e) {e.printStackTrace();if (connection != null) {try {connection.rollback();} catch (SQLException ex) {ex.printStackTrace();}}} finally {try {if (preparedStatement != null) preparedStatement.close();if (connection != null) connection.close();} catch (SQLException e) {e.printStackTrace();}}}@Overridepublic <T> List<T> query(String taskId, String containerName, Class<T> clazz) {List<T> result = new ArrayList<>();Field[] fields = clazz.getDeclaredFields();Map<String, Field> columnToFieldMap = getColumToFieldMap(fields, clazz);Connection connection = null;PreparedStatement preparedStatement = null;ResultSet resultSet = null;try {connection = DriverManager.getConnection(url, userName, password);StringBuilder sql = new StringBuilder("SELECT COUNT(0) FROM ");sql.append(containerName).append(" WHERE task_id='").append(taskId).append("'");preparedStatement = connection.prepareStatement(sql.toString());resultSet = preparedStatement.executeQuery();int total = 0;if (resultSet.next()) {total = resultSet.getInt(1);}resultSet.close();preparedStatement.close();preparedStatement = null;resultSet = null;int totalBatch = (total + batchSize - 1) / batchSize;long id = 0l;List<String> columns = new ArrayList<>(columnToFieldMap.keySet());sql = new StringBuilder("SELECT id,");for (int index = 0; index < columns.size(); index++) {sql.append(columns.get(index)).append(",");}sql.setCharAt(sql.length() - 1, ' ');sql.append(" FROM ").append(containerName).append(" WHERE task_id='").append(taskId).append("' AND id>").append(" ? ").append(" order by id asc").append(" limit ").append(batchSize);System.out.println(sql.toString());preparedStatement = connection.prepareStatement(sql.toString());for (int index = 0; index < totalBatch; index++) {preparedStatement.setLong(1, id);resultSet = preparedStatement.executeQuery();while (resultSet.next()) {T item = clazz.getConstructor().newInstance();id = resultSet.getLong(1);for (int columnIndex = 0; columnIndex < columns.size(); columnIndex++) {Field field = columnToFieldMap.get(columns.get(columnIndex));Class columnClazz = field.getType();if (columnClazz == String.class) {field.set(item, resultSet.getString(columnIndex + 2));} else if (columnClazz == Integer.class) {field.set(item, resultSet.getInt(columnIndex + 2));} else if (columnClazz == Long.class) {field.set(item, resultSet.getLong(columnIndex + 2));} else if (columnClazz == Float.class) {field.set(item, resultSet.getFloat(columnIndex + 2));} else if (columnClazz == Double.class) {field.set(item, resultSet.getDouble(columnIndex + 2));} else if (columnClazz == DateTime.class) {field.set(item, new DateTime(resultSet.getTimestamp(columnIndex + 2).getTime()));} else {throw new RuntimeException("类型不支持!type=" + field.getType().getTypeName());}}result.add(item);}resultSet.close();resultSet = null;}} catch (SQLException | IllegalAccessException | NoSuchMethodException | InvocationTargetException |InstantiationException e) {e.printStackTrace();} finally {try {if (preparedStatement != null) preparedStatement.close();if (connection != null) connection.close();if (resultSet != null) {resultSet.close();}} catch (SQLException e) {e.printStackTrace();}}return result;}private <T> Map<String, Field> getColumToFieldMap(Field[] fields, Class<T> clazz) {Map<String, Field> columnToFieldMap = new HashMap<>();for (Field field : fields) {field.setAccessible(true);ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);if (excelProperty != null) {columnToFieldMap.put(toSnakeCase(field.getName()), field);}}return columnToFieldMap;}private String toSnakeCase(String camelCase) {if (camelCase == null || camelCase.isEmpty()) {return camelCase;}StringBuilder snakeCase = new StringBuilder();boolean capitalizeNext = false;if (!Character.isUpperCase(camelCase.charAt(0))) {snakeCase.append(camelCase.charAt(0));} else {capitalizeNext = true;}for (int i = 1; i < camelCase.length(); i++) {char c = camelCase.charAt(i);if (Character.isUpperCase(c) && (!Character.isUpperCase(camelCase.charAt(i - 1)) || capitalizeNext)) {snakeCase.append('_');c = Character.toLowerCase(c);capitalizeNext = false;}snakeCase.append(c);}return snakeCase.toString();}
}

6. 使用说明

  • 存取的数据结构仅支持非嵌套结构,即一个数据类对应一张数据库表或者一个sheet页;
  • 类字段命名需采用小驼峰格式(如: startTime)且使用ExcelProperty注解进行标注,数据库字段命名需采用蛇形格式(如:start_time);
  • 数据库表必有字段:id-自增主键、task_id-一次仿真的唯一标识;

备注:使用过程中如有问题,可留言~

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

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

相关文章

labview使用斑马打印机打印标签

使用ZebraDesigner 3设计标签样式 设计完成后打印至文件&#xff0c;生成prn文件 用记事本打开prn文件 ^MMT 标签撕下 ^MMP 标签剥离 按照需求替换FD--------^FS中间内容

路由上传一个ui_control参数(uint32类型)控制页面UI显隐

前言&#xff1a;传一个uint32类型的值&#xff0c;通过 按位或操作符&#xff08;|&#xff09;来设置ui_control的值&#xff0c;通过按位与操作符&#xff08;&&#xff09;来检测是否显示或隐藏 简单介绍一下两个概念&#xff1a; 按位与操作符和按位或操作符都是二进…

etcd的备份与恢复

一 为什么使用etcd 与ZooKeeper相比&#xff0c;etcd更简单&#xff0c;安装、部署和使用更加容易&#xff0c;并且etcd的某些功能是ZooKeeper所没有的。因此&#xff0c;在很多场景下&#xff0c;etcd 比ZooKeeper更受用户的青&#xff0c;具体表现在如下几个方面: 1 etcd更…

上海市计算机学会竞赛平台2022年10月月赛丙组门禁记录

题目描述 小爱得到了某大楼一天内按时间顺序记录的&#x1d45b;n条门禁出入记录&#xff0c;每条记录由两个字符串组成&#xff0c;第一个字符串为出入人员姓名&#xff0c;第二个字符串表示该人员进出状态、为 enter 或 exit 中一项&#xff0c;其中 enter 为进入&#xff0…

鑫创SSS1700USB音频桥芯片USB转IIS芯片

鑫创SSS1700支持IIC初始外部编&#xff08;EEPROM选项),两线串行总线&#xff08;I2C总线&#xff09;用于外部MCU控制整个EEPROM空间可以通过MCU访问用于主机控制同步的USB HID外部串行EEPROM&#xff08;24C02~24C16&#xff09;接口&#xff0c;用于客户特定的USB视频、PID、…

jmeter之变量随机参数化以及解决多线程不会随机变化

参考链接&#xff1a; https://www.cnblogs.com/Testing1105/p/12743475.html jmeter 使用random函数多线程运行时数据不会随机变化&#xff1f;_jmeter 线程组循环执行时 变量不变-CSDN博客 1、如下图所示&#xff0c;需要对请求参数 autor 和phone进行随机参数化 2、目前有…

MyBatis源码中的设计模式2

组合模式的应用 组合模式介绍 组合模式(Composite Pattern) 的定义是&#xff1a;将对象组合成树形结构以表示整体和部分的层次结构。组合模式可以让用户统一对待单个对象和对象的组合。 比如&#xff1a;Windows操作系统中的目录结构&#xff0c;通过tree命令实现树形结构展…

【系统架构设计师】十二、系统质量属性与架构评估(开发期质量属性|运行期质量属性|面向架构评估的质量属性|质量属性效用树|质量属性场景)

目录 一、软件系统质量属性 1.1 开发期质量属性 1.2 运行期质量属性 1.3 面向架构评估的质量属性 1.4 质量属性效用树 1.5 质量属性场景 1.5.1 可用性质量属性场景描述 1.5.2 可修改性质量属性场景描述 1.5.3 性能质量属性场景描述 相关推荐 历年真题练习 历…

【vue】输入框和文本域切换

输入框的样子 文本域的样子 当输入框出现滚动条的时候&#xff0c;就自动切换成文本域&#xff1b;当文本域到1行并且宽度小于输入框宽度时切换成输入框 <div class"left_box_inpt"><divclass"right_box_inpt":class"{notclickable: inputd…

OpenResty使用Lua笔记

文章目录 一、基础1、常用2、使用局部变量3、模块化 二、性能提升1、使用fft调用shell2、不要在循环中拼接字符串3、不要频繁修改table4、不要在table中用nil5、做好异常处理6、ngx.var 的性能提升 三、拓展1、加载字符串为动态方法 一、基础 1、常用 OpenResty 中文官网&…

Open3D 最小二乘法拟合点云平面

目录 一、概述 1.1最小二乘法原理 1.2实现步骤 1.3应用场景 二、代码实现 2.1关键函数 2.2完整代码 三、实现效果 3.1原始点云 3.2matplotlib可视化 3.3平面拟合方程 前期试读&#xff0c;后续会将博客加入该专栏&#xff0c;欢迎订阅 Open3D点云算法与点云深度学习…

【学术会议征稿】第四届人工智能、虚拟现实与可视化国际学术会议(AIVRV 2024)

第四届人工智能、虚拟现实与可视化国际学术会议&#xff08;AIVRV 2024&#xff09; 2024 4th International Conference on Artificial Intelligence, Virtual Reality and Visualization 第四届人工智能、虚拟现实与可视化国际学术会议&#xff08;AIVRV 2024&#xff09;将…

用python写一个爬虫,爬取google中关于蛇的照片

为了爬取Google中关于蛇的照片&#xff0c;我们可以利用Python中的第三方库进行网页解析和HTTP请求。请注意&#xff0c;这种爬取行为可能违反Google的使用条款&#xff0c;因此建议在合法和允许的情况下使用。以下是一个基本的Python爬虫示例&#xff0c;使用Requests库发送HT…

git 指令速查

1. 创建命令 Create Git 指令命令说明git clone 克隆远程仓库git init初始化本地 git 仓库(即创建新的本地仓库)2. 本地更改 Local Changes Git 指令命令说明git status查看当前分支状态git diff查看已跟踪文件的变更git add 将指定的文件添加到暂存区git add .将所有有变更的…

简约唯美的404HTML源码

源码介绍 简约唯美的404HTML源码,很适合做网站错误页,将下面的源码放到一个空白的html里面,然后上传到服务器里面即可使用 效果预览 完整源码 <!DOCTYPE html> <html><head><meta charset="utf-8"><title>404 Error Example<…

第二证券:市场估值依然处于较低区域 适合中长期布局

A股中报成绩预告显示相比2024Q1&#xff0c;2024Q2企业产品销量或订单已有回暖&#xff0c;但价格反转暂未大面积到来&#xff0c;“量增价平、部分板块以价换量”是2024H1 A股成绩预告较显着的量价特征&#xff0c;这与微观库存周期有待回暖相匹配。此外中游部分环节出现不同程…

Vue 3中使用 Lottie 动画

一、Lottie动画简介 Lottie是由Airbnb开源的面向Android、iOS、Web和Windows的动画库,开发者可以使用它在Web、iOS、Android等平台上实现高性能的体验丰富的矢量动画。 在早期的前端开发中,Flash是网页动画之王,不过它的规范约束随意,造成很多时设计出来的产品都无法符合…

新版网页无插件H.265播放器EasyPlayer.js如何测试demo视频?

H5无插件流媒体播放器EasyPlayer属于一款高效、精炼、稳定且免费的流媒体播放器&#xff0c;可支持多种流媒体协议播放&#xff0c;支持H.264与H.265编码格式&#xff0c;性能稳定、播放流畅&#xff1b;支持WebSocket-FLV、HTTP-FLV&#xff0c;HLS&#xff08;m3u8&#xff0…

富格林:直面暗箱减少出金亏损

富格林悉知&#xff0c;在交易的过程中&#xff0c;投资者就算做好了十足的把握&#xff0c;也难免会出现出金亏损的情况。在这里建议新手投资者&#xff0c;在准备投资交易的时候&#xff0c;一定要做好充分的准备工作&#xff0c;了解黄金投资哪些暗箱陷阱&#xff0c;同时学…

【Linux】进程信号 --- 信号产生

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前正在学习c和算法 ✈️专栏&#xff1a;Linux &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章有啥瑕疵&#xff0c;希望大佬指点一二 如果文章对…