当前位置: 首页 > news >正文

Java实现excel表数据的批量存储(结合easyexcel插件)

场景:加哥最近在做项目时,苦于系统自身并未提供数据批量导入的功能还不能自行添加上该功能,且自身不想手动一条一条将数据录入系统。随后,自己使用JDBC连接数据库、使用EasyExcel插件读取表格并将数据按照业务逻辑批量插入数据库完成数据的初始化。接下来就看看加哥是怎么做的呢?

第一步:创建一个maven项目并导入依赖。

结合项目需要,只需要数据库和easyexcel的依赖包(在这里加哥使用的是mysql数据库,引入的就是mysql的数据库驱动,如果你想用sqlServer等数据库自行更换依赖就行)。

 

<!--数据库驱动-->
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.21</version>
</dependency>
<!--表格导入处理-->
<dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.1.3</version>
</dependency>

第二步:手写或者准备好JDBC连接、操作数据库的工具类。

在这里加哥是把JDBC连接数据库、操作数据库、关闭数据库封装成了工具类并用static修饰作为静态方法,方便后面使用时候直接使用类型.方法调用。

以下是数据库的驱动、url、用户名、密码定义

//驱动
private static String driver = "com.mysql.jdbc.Driver";
//URL
private static String url = "jdbc:mysql://127.0.0.1:3306/mytestcharacterEncoding=utf-8&serverTimezone=Asia/Shanghai";
//用户名
private static String username = "root";
// 密码
private static String pwd = "123456";

连接数据库的方法,由于使用比较频繁将其抽取为一个独立的方法,该方法主要是加载驱动、创建连接。自己可以定义好后,在main方法中直接调用若执行通过则和数据库建立连接成功,否则失败。

/*** 创建连接* @return*/
public static Connection getConnection(){Connection connection=null;//加载驱动try {Class.forName(driver);} catch (ClassNotFoundException e) {e.printStackTrace();}//建立连接获取Connection对象try {connection= DriverManager.getConnection(url,username,pwd);} catch (SQLException e) {e.printStackTrace();}return connection;
}

关闭连接,由于每次创建连接、都会有一个新的连接打开,如果一直不关闭就会出现连接建立满了的情况,也容易造成资源浪费,因为每次都必须关闭则也将其抽取成一个独立的方法。

/*** 关闭链接* @param connection* @param statement* @param resultSet*/
public static void closeAll(Connection connection, Statement statement, ResultSet resultSet){try {if(resultSet!=null){resultSet.close();}if(statement!=null){statement.close();}if (connection!=null){connection.close();}} catch (SQLException e) {e.printStackTrace();}
}

封装增删改方法,由于增删改调用的方法一致,则可以将其抽取成一个公用方法,在后面需要的时候直接调用该方法即可。查询方法由于每次处理的数据不一致,不适合做成公用方法。

/*** 执行增、删、改的方法* @param sql* @return*/
public static int execute(String sql){//获取链接Connection connection=getConnection();int flag=0;try {//创建Statement对象Statement statement=connection.createStatement();//执行sql语句flag=statement.executeUpdate(sql);//关闭链接closeAll(connection,statement,null);} catch (SQLException e) {e.printStackTrace();}return flag;
}

最后,为了保证我们写的方法可以正常建立连接、关闭连接、完成对应操作,需要大家创建一个main方法完成测试,下面是加哥给大家提供的。但是你在测试过程中,必须保证自己的数据库及其表、表字段都存在。

/*测试*/
public static void main(String[] args) {String sql = "SELECT * FROM bs_structure  WHERE id = 1688350472671";Connection connection = getConnection();Statement statement = null;try {statement= connection.createStatement();ResultSet resultSet = statement.executeQuery(sql);while(resultSet.next()){String typename = resultSet.getString(3);System.out.println("类别名称:"+typename);}} catch (SQLException e) {e.printStackTrace();}
}

第三步、创建实体类

实体类的属性必须和excel表格的列数一致,一般有多少列就会定义多少个属性,这里的实体类就是为了后面读取表格时映射处理使用的。以下是加哥的表格式,由于模版有12列则加哥定义了12个属性。大家可以结合自己excel表格的实际情况去完成。

 实体类

public class Structure {@ExcelProperty(value = "序号", index = 0)private String param1;@ExcelProperty(value = "水厂", index = 1)private String param2;@ExcelProperty(value = "工艺", index = 2)private String param3;@ExcelProperty(value = "设备", index = 3)private String param4;@ExcelProperty(value = "测点", index = 4)private String param5;@ExcelProperty(value = "点长名", index = 6)private String param6;@ExcelProperty(value = "点描述", index = 7)private String param7;@ExcelProperty(value = "设备类型名称", index = 11)private String param8;@ExcelProperty(value = "数据类型", index = 8)private String param9;@ExcelProperty(value = "小数位数", index = 9)private String param10;@ExcelProperty(value = "单位", index = 10)private String param11;@ExcelProperty(value = "测点名称", index = 5)private String param12;public String getParam1() {return param1;}public void setParam1(String param1) {this.param1 = param1;}public String getParam2() {return param2;}public void setParam2(String param2) {this.param2 = param2;}public String getParam3() {return param3;}public void setParam3(String param3) {this.param3 = param3;}public String getParam4() {return param4;}public void setParam4(String param4) {this.param4 = param4;}public String getParam5() {return param5;}public void setParam5(String param5) {this.param5 = param5;}public String getParam6() {return param6;}public void setParam6(String param6) {this.param6 = param6;}public String getParam7() {return param7;}public void setParam7(String param7) {this.param7 = param7;}public String getParam8() {return param8;}public void setParam8(String param8) {this.param8 = param8;}public String getParam9() {return param9;}public void setParam9(String param9) {this.param9 = param9;}public String getParam10() {return param10;}public void setParam10(String param10) {this.param10 = param10;}public String getParam11() {return param11;}public void setParam11(String param11) {this.param11 = param11;}public String getParam12() {return param12;}public void setParam12(String param12) {this.param12 = param12;}
}

第四步、定义DAO层

在DAO层定义并实现自己需要操作数据库表的方法,加哥在这里直接在DAO层实现并区分接口和实现类,大家可以区分开来做。

public String selectParentId(String param) throws SQLException {String sql = "select id from bs_structure where structure_name='" + param + "'";Connection connection = BaseDao.getConnection();Statement statement = connection.createStatement();ResultSet resultSet = statement.executeQuery(sql);String id = "";while (resultSet.next()) {id = resultSet.getString(1);}BaseDao.closeAll(connection,statement,resultSet);return id;}public String selectParentId1(String param,String param1) throws SQLException {String sql = "select id from bs_structure where structure_name='" + param + "' and parent_uuid= '"+param1+"'";Connection connection = BaseDao.getConnection();Statement statement = connection.createStatement();ResultSet resultSet = statement.executeQuery(sql);String id = "";while (resultSet.next()) {id = resultSet.getString(1);}BaseDao.closeAll(connection,statement,resultSet);return id;}public String selectCedianId1(String param,String param1) throws SQLException {String sql = "select id from bs_monitor_attr where structure_uuid='" + param + "' and tag_long_name= '"+param1+"'";Connection connection = BaseDao.getConnection();Statement statement = connection.createStatement();ResultSet resultSet = statement.executeQuery(sql);String id = "";while (resultSet.next()) {id = resultSet.getString(1);}BaseDao.closeAll(connection,statement,resultSet);return id;}public String selectObjectId(String objectType, String typename) throws SQLException {String sql = "SELECT id FROM `bs_object` where object_type='" + objectType + "' and type_name='" + typename + "'";Connection connection = BaseDao.getConnection();Statement statement = connection.createStatement();ResultSet resultSet = statement.executeQuery(sql);String id = "";while (resultSet.next()) {id = resultSet.getString(1);}BaseDao.closeAll(connection,statement,resultSet);return id;
}
public String selectObjectId1(String typename) throws SQLException {String sql = "SELECT id FROM `bs_object` where type_name='" + typename + "'";Connection connection = BaseDao.getConnection();Statement statement = connection.createStatement();ResultSet resultSet = statement.executeQuery(sql);String id = "";while (resultSet.next()) {id = resultSet.getString(1);}BaseDao.closeAll(connection,statement,resultSet);return id;
}
/*** 基本信息表数据填充** @param id* @param structureUuid* @param structureInfoCode* @param structureinfovalue* @return*/
public int insertStructure(String id, String structureUuid, String structureInfoCode, String structureinfovalue) {String sql = "insert into bs_structure_info (id,structure_uuid,structure_info_code,structure_info_value) values ('" + id + "','" + structureUuid + "','" + structureInfoCode + "','" + structureinfovalue + "')";return BaseDao.execute(sql);
}public int insertSbtype(Structure structure) {Calendar cal = Calendar.getInstance();String utcTime=String.valueOf(cal.getTimeInMillis());String sql = "insert into bs_object (id,object_type,type_name,type_code) values ('" + utcTime + "','" + structure.getParam2() + "','" + structure.getParam3() + "','" + structure.getParam4() + "')";Calendar cal1 = Calendar.getInstance();String utcTime1=String.valueOf(cal1.getTimeInMillis());String sql1 = "insert into bs_object_param (id,object_uuid,param_uuid,param_val) values ('" + utcTime1 + "','" + utcTime + "','f4ae866d-937a-11ec-9c0b-00ff8dea45f7','')";BaseDao.execute(sql);return BaseDao.execute(sql1);
}/*** 根据名称查询类型** @param name* @return* @throws SQLException*/
public String selectSbtypeByName(String name) throws SQLException {String sql = "select id from bs_object where type_name='" + name + "'";Connection connection = BaseDao.getConnection();Statement statement = connection.createStatement();ResultSet resultSet = statement.executeQuery(sql);String id = "";while (resultSet.next()) {id = resultSet.getString(1);}BaseDao.closeAll(connection,statement,resultSet);return id;
}/*** 保存设备实例数据* @param id* @param object_uuid* @param structure_name* @param parent_uuid* @param if_scrap* @param if_logic_delete* @param if_restrain* @param object_type* @param structure_code* @param type_name* @param if_issued* @return*/
public int saveStructure(String id, String object_uuid, String structure_name, String parent_uuid, String if_scrap, String if_logic_delete, String if_restrain, String object_type, String structure_code, String type_name, String if_issued) {String sql = "INSERT INTO `bs_structure` \n" +"\t(`id`, \n" +"\t`object_uuid`, \n" +"\t`structure_name`, \n" +"\t`parent_uuid`, \n" +"\t`if_scrap`, \n" +"\t`object_type`, \n" +"\t`structure_code`, \n" +"\t`type_name`, \n" +"\t`if_issued`\n" +"\t)\n" +"\tVALUES\n" +"\t('"+id+"', \n" +"\t'"+object_uuid+"', \n" +"\t'"+structure_name+"', \n" +"\t'"+parent_uuid+"', \n" +"\t'"+if_scrap+"', \n" +"\t'"+object_type+"', \n" +"\t'"+structure_code+"', \n" +"\t'"+type_name+"', \n" +"\t'"+if_issued+"'\n" +"\t);\n";return BaseDao.execute(sql);
}/*** 插入数据** @param id* @param objectId* @param pointName* @param tagDescribe* @param dataType* @param readOrWrite* @param decimal* @param unit* @param inShow* @param ifshow3d* @param ifrange* @return*/
public int insertObjectMonitor(String id, String objectId, String pointName, String tagDescribe, String pointType, String dataType, String readOrWrite, String decimal, String unit, String inShow, String ifshow3d, String ifrange) {String sql = "insert into bs_object_monitor_attr (id,object_id,point_name,tag_describe,point_type,data_type,read_or_write,decimal_digit,unit,if_show,if_show_3d,if_ranging) values ('" + id + "','" + objectId + "','" + pointName + "','" + tagDescribe + "','" + pointType + "','" + dataType + "','" + readOrWrite + "','" + decimal + "','" + unit + "','" + inShow + "','" + ifshow3d + "','" + ifrange + "')";return BaseDao.execute(sql);
}/*** 根据对象类型id获取测点信息数据** @param name* @return* @throws SQLException*/
public String selectCedianInfoByobjid(String name,String name1) throws SQLException {String sql = "select id from bs_object_monitor_attr where point_name='" + name + "' and object_id='"+name1+"'";Connection connection = BaseDao.getConnection();Statement statement = connection.createStatement();ResultSet resultSet = statement.executeQuery(sql);String id = "";while (resultSet.next()) {id = resultSet.getString(1);}BaseDao.closeAll(connection,statement,resultSet);return id;
}/*** 根据单位名称获取单位的id* @param name* @return* @throws SQLException*/
public String selectUnitIdByName(String name) throws SQLException {String sql="SELECT id FROM `bs_unit` where unit_name='"+name+"'";Connection connection = BaseDao.getConnection();Statement statement = connection.createStatement();ResultSet resultSet = statement.executeQuery(sql);String id = "";while (resultSet.next()) {id = resultSet.getString(1);}BaseDao.closeAll(connection,statement,resultSet);return id;
}

第五步、定义Service层

在Service层定义数据的保存方法,便于处理时候调用。

 /*** 上一行数据的存储*/public Structure afterData;/*** 数据持久化* @param cachedDataList* @throws SQLException*/public void saveStructure(List<Structure> cachedDataList) throws SQLException, InterruptedException {System.out.println(cachedDataList);StructureDao structureDao =new StructureDao();for(int i=1;i<cachedDataList.size();i++){//等待Structure structure=cachedDataList.get(i);//若出现合并行将其合并行的数据填充进来if("".equals(structure.getParam2())||null==structure.getParam2()){structure.setParam2(afterData.getParam2());}if("".equals(structure.getParam3())||null==structure.getParam3()){structure.setParam3(afterData.getParam3());}if("".equals(structure.getParam4())||null==structure.getParam4()){structure.setParam4(afterData.getParam4());}if("".equals(structure.getParam5())||null==structure.getParam5()){structure.setParam5(afterData.getParam5());}if("".equals(structure.getParam6())||null==structure.getParam6()){structure.setParam6(afterData.getParam6());}if("".equals(structure.getParam7())||null==structure.getParam7()){structure.setParam7(afterData.getParam7());}if("".equals(structure.getParam8())||null==structure.getParam8()){structure.setParam8(afterData.getParam8());}//先判断第一个节点是否存在,存在的话查询它的idString parentID= structureDao.selectParentId(structure.getParam2());Calendar cal = Calendar.getInstance();//将点长名进行拆分String[] changmingchaifens=structure.getParam6().split("/");if(parentID==""&&parentID.equals("")){//获取object对应关系表String objectID= structureDao.selectObjectId("非设备","厂区");//不存在String preUuid =String.valueOf(cal.getTimeInMillis())+(int)(1+Math.random()*100);//System.out.println("preUuid0"+preUuid);int flag=  structureDao.saveStructure(preUuid, objectID, structure.getParam2(), "1688107649766",  "", "", "", "非设备", changmingchaifens[0], "厂区", "false");if(flag==1){parentID=preUuid;}//提交节点的基本信息表获取数据structureDao.insertStructure(UUID.randomUUID().toString().replace("-", ""),parentID,"type_name","厂区");structureDao.insertStructure(UUID.randomUUID().toString().replace("-", ""),parentID,"f4ae8186-937a-11ec-9c0b-00ff8dea45f7","116.404,39.915,0,0,13");structureDao.insertStructure(UUID.randomUUID().toString().replace("-", ""),parentID,"f4ae866d-937a-11ec-9c0b-00ff8dea45f7","getPtFormHtml?code=Bd_DeviceDetails");}//判断工艺节点是否存在String parentIdOfGy= structureDao.selectParentId1(structure.getParam3(),parentID);if(parentIdOfGy==""&&parentIdOfGy.equals("")){//获取object对应关系表String objectID= structureDao.selectObjectId("非设备","管理节点");TimeUnit.MILLISECONDS.sleep(1);//不存在String preUuid = String.valueOf(cal.getTimeInMillis())+(int)(1+Math.random()*100);int flag=  structureDao.saveStructure(preUuid, objectID, structure.getParam3(), parentID,"", "", "", "非设备", changmingchaifens[1], "管理节点", "false");if(flag==1){parentIdOfGy=preUuid;}//提交节点的基本信息表获取数据structureDao.insertStructure(UUID.randomUUID().toString().replace("-", ""),parentIdOfGy,"type_name","管理节点");structureDao.insertStructure(UUID.randomUUID().toString().replace("-", ""),parentIdOfGy,"f4ae8186-937a-11ec-9c0b-00ff8dea45f7","116.404,39.915,0,0,13");structureDao.insertStructure(UUID.randomUUID().toString().replace("-", ""),parentIdOfGy,"f4ae866d-937a-11ec-9c0b-00ff8dea45f7","getPtFormHtml?code=Bd_DeviceDetails");}//判断设备是否存在:根据他的父节点及其设备名称判断是否存在若不存在进行导入String parentIdOfSb= structureDao.selectParentId1(structure.getParam4(),parentIdOfGy);if(parentIdOfSb==""&&parentIdOfSb.equals("")){//获取object对应关系表String objectID= structureDao.selectObjectId1(structure.getParam8());TimeUnit.MILLISECONDS.sleep(1);//不存在String preUuid = String.valueOf(cal.getTimeInMillis())+(int)(1+Math.random()*100);int flag=  structureDao.saveStructure(preUuid, objectID, structure.getParam4(), parentIdOfGy,"", "", "","设备",preUuid, structure.getParam8(), "false");if(flag==1){parentIdOfSb=preUuid;}//测点信息录入String preUuidcd = String.valueOf(cal.getTimeInMillis());String[] point_names=structure.getParam5().split("_");String[] tag_describes=structure.getParam7().split("_");String sql1="";if(null==structure.getParam10()&&null==structure.getParam11()){//不保存数据位数//System.out.println(structure.getParam6());String longName="/"+structure.getParam6();sql1= "insert into bs_monitor_attr (id,structure_uuid,point_name,tag_describe,data_type,read_or_write,data_source,tag_long_name) values ('"+preUuidcd+"','"+parentIdOfSb+"','"+structure.getParam12()+"','"+tag_describes[tag_describes.length-1]+"','"+structure.getParam9()+"','只读','2','"+longName+"')";}else{String longName="/"+structure.getParam6();sql1= "insert into bs_monitor_attr (id,structure_uuid,point_name,tag_describe,data_type,read_or_write,data_source,tag_long_name,decimal_digit,unit) values ('"+preUuidcd+"','"+parentIdOfSb+"','"+structure.getParam12()+"','"+tag_describes[tag_describes.length-1]+"','"+structure.getParam9()+"','只读','2','"+longName+"','"+Integer.valueOf(structure.getParam10())+"','"+structureDao.selectUnitIdByName(structure.getParam11())+"')";}int flag1=BaseDao.execute(sql1);//根据名称查询设备类型idString object_id= structureDao.selectObjectId1(structure.getParam8());//根据测点名称判断数据是否存在String cedianId= structureDao.selectCedianInfoByobjid(structure.getParam12(),object_id);if(cedianId==""&&cedianId.equals("")){//不存在//将测点数据同步至设备类型对应的bs_object_monitor_attr里面structureDao.insertObjectMonitor(String.valueOf(cal.getTimeInMillis()),object_id,structure.getParam12(),tag_describes[tag_describes.length-1],"",structure.getParam9(),"只读",structure.getParam10(),structureDao.selectUnitIdByName(structure.getParam11()),"1","1","1");}//提交节点的基本信息表获取数据structureDao.insertStructure(UUID.randomUUID().toString().replace("-", ""),parentIdOfSb,"type_name",structure.getParam8());structureDao.insertStructure(UUID.randomUUID().toString().replace("-", ""),parentIdOfSb,"f4ae8186-937a-11ec-9c0b-00ff8dea45f7","116.404,39.915,0,0,13");structureDao.insertStructure(UUID.randomUUID().toString().replace("-", ""),parentIdOfSb,"f4ae866d-937a-11ec-9c0b-00ff8dea45f7","getPtFormHtml?code=Bd_DeviceDetails");System.out.println("第{"+(i)+"}条数据,存储至数据库完成!");}else{//判断测点信息在不在//测点信息录入,根据设备id与长名判断是否一致,若不一致则录入String[] point_names=structure.getParam5().split("_");//根据测点名称判断数据是否存在String longName1="/"+structure.getParam6();String cedianId0 = structureDao.selectCedianId1(parentIdOfSb,longName1);if(cedianId0==""&&cedianId0.equals("")){//录入String preUuidcd = String.valueOf(cal.getTimeInMillis());String[] tag_describes=structure.getParam7().split("_");String sql1="";if(null==structure.getParam10()&&null==structure.getParam11()){//不保存数据位数String longName="/"+structure.getParam6();sql1= "insert into bs_monitor_attr (id,structure_uuid,point_name,tag_describe,data_type,read_or_write,data_source,tag_long_name) values ('"+preUuidcd+"','"+parentIdOfSb+"','"+structure.getParam12()+"','"+tag_describes[tag_describes.length-1]+"','"+structure.getParam9()+"','只读','2','"+longName+"')";}else{String longName="/"+structure.getParam6();sql1= "insert into bs_monitor_attr (id,structure_uuid,point_name,tag_describe,data_type,read_or_write,data_source,tag_long_name,decimal_digit,unit) values ('"+preUuidcd+"','"+parentIdOfSb+"','"+structure.getParam12()+"','"+tag_describes[tag_describes.length-1]+"','"+structure.getParam9()+"','只读','2','"+longName+"','"+Integer.valueOf(structure.getParam10())+"','"+structureDao.selectUnitIdByName(structure.getParam11())+"')";}int flag1=BaseDao.execute(sql1);//根据名称查询设备类型idString object_id= structureDao.selectObjectId1(structure.getParam8());String cedianId= structureDao.selectCedianInfoByobjid(structure.getParam12(),object_id);if(cedianId==""&&cedianId.equals("")){//不存在//将测点数据同步至设备类型对应的bs_object_monitor_attr里面structureDao.insertObjectMonitor(String.valueOf(cal.getTimeInMillis()),object_id,structure.getParam12(),tag_describes[tag_describes.length-1],"",structure.getParam9(),"只读",structure.getParam10(),structureDao.selectUnitIdByName(structure.getParam11()),"1","1","1");}//提交节点的基本信息表获取数据/*   structureDao.insertStructure(UUID.randomUUID().toString().replace("-", ""),parentIdOfSb,"type_name",structure.getParam8());structureDao.insertStructure(UUID.randomUUID().toString().replace("-", ""),parentIdOfSb,"f4ae8186-937a-11ec-9c0b-00ff8dea45f7","116.404,39.915,0,0,13");structureDao.insertStructure(UUID.randomUUID().toString().replace("-", ""),parentIdOfSb,"f4ae866d-937a-11ec-9c0b-00ff8dea45f7","getPtFormHtml?code=Bd_DeviceDetails");
*/System.out.println("第{"+(i)+"}条数据,存储至数据库完成!");}else {System.out.println("第{"+(i)+"}条数据已存在,已跳过该条记录!");}}//数据缓存afterData=cachedDataList.get(i);}}

第六步,使用EasyExcel批量读取并保存数据

大家可以打开easyexcel官网选择自己适合的读取方法,下面展示出来的仅是一种,读取数据并保存数据,在保存数据里面替换成自己的service层的保存方法即可。

String fileName = "D:\\实例表.xlsx";// 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭
EasyExcel.read(fileName, Structure.class, new ReadListener<Structure>() {/*** 单次缓存的数据量*/public static final int BATCH_COUNT = 1000;/***临时存储的数据*/private List<Structure> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);@Overridepublic void invoke(Structure data, AnalysisContext context) {cachedDataList.add(data);if (cachedDataList.size() >= BATCH_COUNT) {try {saveData();} catch (SQLException | InterruptedException e) {e.printStackTrace();}finally {// 存储完成清理 listcachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);}}}@Overridepublic void doAfterAllAnalysed(AnalysisContext context) {try {saveData();} catch (SQLException | InterruptedException e) {e.printStackTrace();}}/*** 加上存储数据库*/private void saveData() throws SQLException, InterruptedException {StructureService structureService=new StructureService();structureService.saveStructure(cachedDataList);}
}).sheet().doRead();

第七步,去数据库查看是否存储成功并检查数据是否正确。

相关文章:

Java实现excel表数据的批量存储(结合easyexcel插件)

场景&#xff1a;加哥最近在做项目时&#xff0c;苦于系统自身并未提供数据批量导入的功能还不能自行添加上该功能&#xff0c;且自身不想手动一条一条将数据录入系统。随后&#xff0c;自己使用JDBC连接数据库、使用EasyExcel插件读取表格并将数据按照业务逻辑批量插入数据库完…...

Config:客户端连接服务器访问远程

springcloud-config: springcloud-config push pom <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocatio…...

【KMP算法-代码随想录】

目录 1.什么是KMP2.什么是next数组3.什么是前缀表&#xff08;1&#xff09;前后缀含义&#xff08;2&#xff09;最长公共前后缀&#xff08;3&#xff09;前缀表的必要性 4.计算前缀表5.前缀表与next数组&#xff08;1&#xff09;使用next数组来匹配 6.构造next数组&#xf…...

【手写promise——基本功能、链式调用、promise.all、promise.race】

文章目录 前言一、前置知识二、实现基本功能二、实现链式调用三、实现Promise.all四、实现Promise.race总结 前言 关于动机&#xff0c;无论是在工作还是面试中&#xff0c;都会遇到Promise的相关使用和原理&#xff0c;手写Promise也有助于学习设计模式以及代码设计。 本文主…...

计算机网络-笔记-第二章-物理层

目录 二、第二章——物理层 1、物理层的基本概念 2、物理层下面的传输媒体 &#xff08;1&#xff09;光纤、同轴电缆、双绞线、电力线【导引型】 &#xff08;2&#xff09;无线电波、微波、红外线、可见光【非导引型】 &#xff08;3&#xff09;无线电【频谱的使用】 …...

前端开发中的单伪标签清除和双伪标签清除

引言 在前端开发中&#xff0c;我们经常会遇到一些样式上的问题&#xff0c;其中之一就是伪元素造成的布局问题。为了解决这个问题&#xff0c;我们可以使用伪标签清除技术。本篇博客将介绍单伪标签清除和双伪标签清除的概念、用法和示例代码&#xff0c;并详细解释它们的原理…...

云计算中的数据安全与隐私保护策略

文章目录 1. 云计算中的数据安全挑战1.1 数据泄露和数据风险1.2 多租户环境下的隔离问题 2. 隐私保护策略2.1 数据加密2.2 访问控制和身份验证 3. 应对方法与技术3.1 零知识证明&#xff08;Zero-Knowledge Proofs&#xff09;3.2 同态加密&#xff08;Homomorphic Encryption&…...

MacOS软件安装包分享(附安装教程)

目录 一、软件简介 二、软件下载 一、软件简介 MacOS是一种由苹果公司开发的操作系统&#xff0c;专门用于苹果公司的计算机硬件。它被广泛用于创意和专业应用程序&#xff0c;如图像设计、音频和视频编辑等。以下是关于MacOS的详细介绍。 1、MacOS的历史和演变 MacOS最初于…...

【linux进程概念】

目录&#xff1a; 冯诺依曼体系结构操作系统进程 基本概念描述进程-PCBtask_struct-PCB的一种task_ struct内容分类组织进程查看进程 fork()函数 冯诺依曼体系结构 我们常见的计算机&#xff0c;如笔记本。我们不常见的计算机&#xff0c;如服务器&#xff0c;大部分都遵守冯诺…...

直击成都国际车展:远航汽车多款车型登陆车展,打造完美驾乘体验

随着市场渗透率日益高涨&#xff0c;新能源汽车成为今年成都国际车展的关注焦点。在本届车展上&#xff0c;新能源品牌占比再创新高&#xff0c;覆盖两个展馆&#xff0c;印证了当下新能源汽车市场的火爆。作为大运集团重磅打造的高端品牌&#xff0c;远航汽车深度洞察高端智能…...

android nv21 转 yuv420sp

上面两个函数的目标都是将NV21格式的数据转换为YUV420P格式&#xff0c;但是它们在处理U和V分量的方式上有所不同。 在第一个函数NV21toYUV420P_1中&#xff0c;U和V分量的处理方式是这样的&#xff1a;对于U分量&#xff0c;它从NV21数据的Y分量之后的每个奇数位置取数据&…...

使用Nacos与Spring Boot实现配置管理

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…...

初识【类和对象】

目录 1.面向过程和面向对象初步认识 2.类的引入 3.类的定义 4.类的访问限定符及封装 5.类的作用域 6.类的实例化 7.类的对象大小的计算 8.类成员函数的this指针 1.面向过程和面向对象初步认识 C语言是面向过程的&#xff0c;关注的是过程&#xff0c;分析出求解问题的…...

软考高级系统架构设计师系列论文八十六:论企业应用集成

软考高级系统架构设计师系列论文八十六:论企业应用集成 一、企业应用集成相关知识点二、摘要三、正文四、总结一、企业应用集成相关知识点 软考高级系统架构设计师系列之:企业集成平台技术的应用和架构设计二、摘要 2022年10月,我参加了***车站综合信息平台项目的开发,承…...

HarmonyOS ArkUI 属性动画入门详解

HarmonyOS ArkUI 属性动画入门详解 前言属性动画是什么&#xff1f;我们借助官方的话来说&#xff0c;我们自己简单归纳下 参数解释举个例子旋转动画 位移动画组合动画总结 前言 鸿蒙OS最近吹的很凶&#xff0c;赶紧卷一下。学习过程中发现很多人吐槽官方属性动画这一章比较敷…...

基于XGBoots预测A股大盘《上证指数》(代码+数据+一键可运行)

对AI炒股感兴趣的小伙伴可加WX&#xff1a;caihaihua057200&#xff08;备注&#xff1a;学校/公司名字方向&#xff09; 另外我还有些AI的应用可以一起研究&#xff08;我一直开源代码&#xff09; 1、引言 在这期内容中&#xff0c;我们回到AI预测股票&#xff0c;转而探索…...

5G NR:PRACH频域资源

PRACH在频域位置由IE RACH-ConfigGeneric中参数msg1-FrequencyStart和msg1-FDM所指示&#xff0c;其中&#xff0c; msg1-FrequencyStart确定PRACH occasion 0的RB其实位置相对于上行公共BWP的频域其实位置(即BWP 0)的偏移&#xff0c;即确定PRACH的频域起始位置msg1-FDM的取值…...

设计模式——组合模式

什么是组合模式 组合模式(Composite Pattern)&#xff1a;组合多个对象形成树形结构以表示具有“整体—部分”关系的层次结构。组合模式对单个对象&#xff08;即叶子对象&#xff09;和组合对象&#xff08;即容器对象&#xff09;的使用具有一致性&#xff0c;组合模式又可以…...

get属性是什么?有什么用?在什么场景用?get会被Json序列化?

在JavaScript中&#xff0c;对象的属性不仅可以是数据属性&#xff08;即常规的键值对&#xff09;&#xff0c;还可以是访问器属性&#xff08;accessor properties&#xff09;。访问器属性不包含实际的数据值&#xff0c;而是定义了如何获取&#xff08;get&#xff09;和设…...

这可能是你看过最详细的 [八大排序算法]

排序算法 前置知识 [排序稳定性]一、直接插入排序二、希尔排序三、直接选择排序四、堆排序五、冒泡排序六、快速排序七、归并排序八、计数排序&#xff08;非比较排序&#xff09;排序复杂度和稳定性总结 前置知识 [排序稳定性] 假定在待排序的记录序列中&#xff0c;存在多个…...

AI时代什么建站软件功能强大?从GEO流量重构看CMS的智慧进化

2026年&#xff0c;互联网的底层逻辑正在发生一场“静默革命”。如果你的思维还停留在“建一个网站只是为了有个官网给客户看”&#xff0c;那么你可能正在被时代抛弃。当下的AI已经不仅仅是一个聊天工具&#xff0c;它正在重构整个信息的传播秩序。传统的SEO&#xff08;搜索引…...

新能源场站通信实战:IEC104与Modbus TCP协议网关开发要点与配置指南

新能源场站通信实战&#xff1a;IEC104与Modbus TCP协议网关开发要点与配置指南 在新能源场站的监控系统中&#xff0c;协议转换网关扮演着至关重要的角色。光伏电站的逆变器、风电场的变流器、充电桩的智能电表等设备通常采用Modbus TCP协议进行数据采集&#xff0c;而电网调度…...

私有化 IM vs 公有云 IM:3 个维度告诉你该怎么选

企业在选择即时通讯工具时&#xff0c;常常陷入 “功能越多越好” 的误区。实际上&#xff0c;IM 选型的本质是一次数据治理策略的决策。私有化 IM 和公有云 IM 没有绝对的好坏&#xff0c;只有适合不适合。今天我们从三个核心维度&#xff0c;帮你做出正确的选择。第一个维度&…...

测试工程师如何进行测试计划制定?这5个步骤让你的计划更合理

对于软件测试从业者而言&#xff0c;一份合理可行的测试计划是项目测试工作的核心纲领&#xff0c;它不仅决定了测试活动的范围、方向与资源分配&#xff0c;更直接影响着项目的交付质量与进度管控。很多初级测试工程师常常将测试计划等同于测试时间列表&#xff0c;要么写得过…...

我见过最聪明的技术人,都在偷偷培养这3种“非技术能力”

在软件测试行业摸爬滚打这些年&#xff0c;我见过太多天赋异禀的技术从业者&#xff1a;有人能一夜吃透新的自动化测试框架&#xff0c;有人能对着流量日志半小时定位出隐藏半年的内存泄漏问题&#xff0c;有人能把性能测试指标优化到远超行业标准。可几年过去&#xff0c;真正…...

m4s-converter:3步解锁B站缓存视频的跨平台免费工具

m4s-converter&#xff1a;3步解锁B站缓存视频的跨平台免费工具 【免费下载链接】m4s-converter 一个跨平台小工具&#xff0c;将bilibili缓存的m4s格式音视频文件合并成mp4 项目地址: https://gitcode.com/gh_mirrors/m4/m4s-converter 你是否曾因B站视频突然下架而感到…...

YOLOv8 ROS 2深度解析:机器人视觉感知系统的架构设计与实践指南

YOLOv8 ROS 2深度解析&#xff1a;机器人视觉感知系统的架构设计与实践指南 【免费下载链接】yolov8_ros Ultralytics YOLOv8, YOLOv9, YOLOv10, YOLOv11, YOLOv12 for ROS 2 项目地址: https://gitcode.com/gh_mirrors/yo/yolov8_ros 在机器人技术快速发展的今天&#…...

FlexNeRFer架构:动态精度MAC与稀疏计算优化解析

1. FlexNeRFer架构设计解析 1.1 多精度MAC单元设计原理 FlexNeRFer的核心创新在于其可动态调整精度的MAC&#xff08;乘加运算单元&#xff09;架构。传统固定精度MAC在面对NeRF这类需要混合精度计算的场景时&#xff0c;要么存在计算资源浪费&#xff08;高精度模式&#xff…...

新手入门教程使用Python快速配置Taotoken的OpenAI兼容API调用环境

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 新手入门教程使用Python快速配置Taotoken的OpenAI兼容API调用环境 对于刚接触大模型API的Python开发者来说&#xff0c;快速搭建一…...

双翌精翌亮相工业软件产业协同对接交流会,共筑国产精密测量新生态

本次交流会以“同心聚链、智造共赢”为主题&#xff0c;汇聚了来自全国各地的工业软件开发商、高端装备制造商、系统集成商以及行业专家&#xff0c;围绕工业软件国产化替代、软硬件协同适配、产业生态共建等核心议题展开深入探讨。在国家信创战略加速推进的大背景下&#xff0…...