【仿真建模-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.pswp.cn/web/45975.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/45975.shtml
英文地址,請注明出處:http://en.pswp.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;希望大佬指點一二 如果文章對…