mybatis 根据多个id查询数据 foreach标签

MyBatis参数传递详解
本文详细解析了在MyBatis中如何正确地传递数组和集合参数,特别是针对collection属性的设置进行了说明,并提供了具体的解决方案。
 //根据设备多个id获取设备信息
    public List<Devices>  getDevicesAll(@Param("devicesIds") String[] devicesIds);



 <select id="getDevicesAll" resultMap="BaseResultMap">
  	select 
  	<include refid="Base_Column_List"/>
  	from sys_devices d 
  	where 
  	d.devices_id  in 
  	<foreach item="devices_id" index="index" collection="devicesIds" 
         	 	open="(" separator="," close=")">
         #{devices_id}
  	</foreach>
	<!-- <where>
  		 <if test="devicesIds != null">
  		 d.devices_id  in 
 		  	<foreach item="item" index="index" collection="array" 
         	 	open="(" separator="," close=")">
         			#{item}
  			</foreach>
		 </if>
  	</where> -->
  </select>

用param标签  

//根据主键ID删除一条记录
    int deleteCategory(String[] categoryId); 


<!-- 根据主键删除一条记录 -->
  <delete id="deleteCategory">
    delete from category
    where Category_ID in
    <foreach item="item" index="index" collection="array" open="(" separator="," close=")">
    #{item}
    </foreach>
  </delete>

这两种方式

 

下面是其他的方式

在MyBatis传入List参数时,MyBatis报错:nested exception is org.apache.ibatis.binding.BindingException: Parameter 'idList' not found. Available parameters are [collection, list]","request_id":"fe7f7f815c1995a6015c1a22c2540234"}

以下是相关代码:

Mapper.java--

mapper.xml

 

解决方案:

修改Mapper.java:

修改mapper.xml

 

 

原因:

foreach元素的属性主要有item,index,collection,open,separator,close。item表示集合中每一个元素进行迭代时的别名,index指定一个名字,用于表示在迭代过程中,每次迭代到的位置,open表示该语句以什么开始,separator表示在每次进行迭代之间以什么符号作为分隔符,close表示以什么结束,在使用foreach的时候最关键的也是最容易出错的就是collection属性,该属性是必须指定的,但是在不同情况下,该属性的值是不一样的,主要有一下3种情况: 

    1. 如果传入的是单参数且参数类型是一个List的时候,collection属性值为list .
    2. 如果传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array .
    3. 如果传入的参数是多个的时候,我们就需要把它们封装成一个Map了,当然单参数也可以封装成map,实际上如果你在传入参数的时候,在MyBatis里面也是会把它封装成一个Map的,map的key就是参数名,所以这个时候collection属性值就是传入的List或array对象在自己封装的map里面的key.
<think>好的,我现在需要解决用户的问题:如何使用Spring Boot实现从多个PLC读取数据并存储到Redis,同时管理PLC配置,通过WebSocket推送到前端。让我一步步理清思路。 首先,用户的需求涉及多个组件:PLC数据采集、Redis存储、WebSocket推送,以及数据库管理配置。我需要整合这些部分,确保各模块协同工作。 1. **PLC数据采集**: PLC通常使用工业协议如Modbus、OPC UA等。需要选择合适的Java库来与PLC通信。例如,Eclipse Milo库支持OPC UA,而Modbus4J可用于Modbus协议。需要根据PLC类型选择对应的依赖库。 用户提到要从多个PLC读取数据,所以需要为每个PLC配置连接参数,比如IP地址、端口、寄存器地址等。这些配置信息存储在数据库中,因此需要设计数据库表来保存这些信息。 2. **数据库配置管理**: 用户希望PLC的配置和数据地址通过数据库管理,所以需要设计一个数据库表结构。可能包括PLC_ID、IP、端口、协议类型、寄存器地址、采集频率等字段。使用Spring Data JPA或MyBatis来操作数据库,方便动态读取配置。 3. **数据存储到Redis**: 使用Spring Boot的RedisTemplate来操作Redis。根据引用[3],配置多数据源Redis可能需要多个Redis连接,但用户的需求可能只需要一个Redis实例存储不同PLC的数据,用不同的key区分。例如,按PLC ID数据类型存储。需要配置Redis连接参数,如引用[1]中的application.properties配置,但可能需要多个配置,如引用[2]和[3]中的多数据源配置,如果用户需要分开存储到不同Redis实例的话。 4. **WebSocket推送数据**: Spring提供了WebSocket支持,可以使用@EnableWebSocket和实现WebSocketHandler来处理前端连接。当PLC数据更新时,将数据通过WebSocket推送到前端。可能需要维护一个Session列表,当有新数据时,遍历Session发送消息。 5. **整体流程**: - 启动时从数据库加载所有PLC配置。 - 为每个PLC创建定时任务,根据采集频率读取数据。 - 读取的数据存入Redis,同时触发WebSocket推送。 - 前端通过WebSocket接收实时数据。 需要考虑的问题: - **多PLC并发读取**:如何高效管理多个PLC的连接,避免阻塞。可能需要使用线程池或异步任务。 - **配置动态更新**:当数据库中的PLC配置更改时,如何动态更新采集任务。可能需要监听数据库变化或提供手动刷新接口。 - **数据存储结构**:在Redis中合理设计数据结构,比如使用Hash存储每个PLC的最新数据,或者按时间序列存储历史数据。 - **异常处理**:PLC连接失败时的重试机制,数据采集的异常捕获,避免整个应用崩溃。 - **性能优化**:高频数据采集可能影响性能,需合理设置采集频率和批量操作Redis。 接下来需要查阅相关技术文档,确认依赖库的兼容性,比如Spring Boot版本与Milo、Redis、WebSocket的整合。例如,引用[3]提到使用Spring Boot 2.0.7和Lettuce,可能需要适配当前Spring Boot版本。 代码结构大致分为: - 配置模块:读取数据库中的PLC配置,初始化数据采集任务。 - 数据采集模块:负责与PLC通信,定时读取数据。 - 数据存储模块:将数据写入Redis。 - WebSocket模块:推送数据到前端。 - 前端界面:展示实时数据。 测试时可能需要模拟PLC设备,使用Mock库或者本地测试服务器。同时,需要确保Redis和数据库的连接正确,WebSocket连接稳定。 可能遇到的问题: - PLC库的兼容性和稳定性。 - 高并发下的数据采集和推送延迟。 - WebSocket的连接管理和断线重连。 需要分步骤实现,先完成单个PLC的数据采集和存储,再扩展为多PLC,最后加入WebSocket推送。确保每一步都经过测试,避免集成时出现难以排查的问题。</think>### 使用Spring Boot实现多PLC数据采集、Redis存储及WebSocket推送 以下是分步骤实现方案,整合PLC数据采集、Redis存储、数据库配置管理及WebSocket推送功能: --- #### 一、环境准备 1. **依赖引入**(`pom.xml`) 添加Spring Boot Web、Spring Data JPA、Redis、WebSocket及PLC协议库依赖(以OPC UA为例): ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> <dependency> <groupId>org.eclipse.milo</groupId> <artifactId>sdk-client</artifactId> <version>0.6.7</version> </dependency> ``` --- #### 二、数据库配置管理 1. **设计PLC配置表** 创建表`plc_config`存储PLC连接信息: ```sql CREATE TABLE plc_config ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(255), protocol VARCHAR(50), -- 协议类型,如OPCUA/Modbus host VARCHAR(100), port INT, data_address VARCHAR(100), -- 数据寄存器地址 collect_interval INT -- 采集间隔(毫秒) ); ``` 2. **JPA实体类** ```java @Entity @Table(name = "plc_config") public class PlcConfig { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; private String protocol; private String host; private Integer port; private String dataAddress; private Integer collectInterval; // Getters & Setters } ``` --- #### 三、Redis配置 1. **单数据源配置**(`application.properties`)[^1] ```properties spring.redis.host=127.0.0.1 spring.redis.port=6379 spring.redis.password= spring.redis.timeout=60000 ``` 2. **多数据源配置**(参考引用[3]) 若需隔离数据存储,可配置多个Redis实例: ```yaml spring: redis: redis1: host: 127.0.0.1 port: 6379 redis2: host: 127.0.0.1 port: 6380 ``` --- #### 四、PLC数据采集与存储 1. **动态加载配置** 通过`@Scheduled`定时任务从数据库读取配置并采集数据: ```java @Service public class PlcDataService { @Autowired private PlcConfigRepository configRepository; @Autowired private RedisTemplate<String, Object> redisTemplate; @Scheduled(fixedDelay = 5000) public void pollPlcData() { List<PlcConfig> configs = configRepository.findAll(); configs.forEach(config -> { Object data = readFromPlc(config); // 调用PLC协议库读取数据 String redisKey = "plc:" + config.getId(); redisTemplate.opsForValue().set(redisKey, data); }); } private Object readFromPlc(PlcConfig config) { // 使用Eclipse Milo等库实现具体协议通信 return "mock_data"; } } ``` --- #### 五、WebSocket实时推送 1. **WebSocket配置类** ```java @Configuration @EnableWebSocket public class WebSocketConfig implements WebSocketConfigurer { @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(new PlcDataHandler(), "/ws/plc-data"); } } ``` 2. **消息处理器** ```java public class PlcDataHandler extends TextWebSocketHandler { private static final List<WebSocketSession> sessions = new CopyOnWriteArrayList<>(); @Override public void afterConnectionEstablished(WebSocketSession session) { sessions.add(session); } public void sendDataToAll(String message) { sessions.forEach(session -> { try { session.sendMessage(new TextMessage(message)); } catch (IOException e) { e.printStackTrace(); } }); } } ``` 3. **数据更新时触发推送** 在`PlcDataService`中注入`PlcDataHandler`,存储数据后调用推送: ```java redisTemplate.opsForValue().set(redisKey, data); plcDataHandler.sendDataToAll(data.toString()); ``` --- #### 六、前端订阅数据 ```javascript const socket = new WebSocket('ws://localhost:8080/ws/plc-data'); socket.onmessage = (event) => { const data = JSON.parse(event.data); console.log('Received:', data); }; ``` --- ### 关键优化点 1. **异步采集**:使用`@Async`避免阻塞主线程。 2. **连接池管理**:优化PLC和Redis连接复用[^3]。 3. **配置热更新**:监听数据库变化动态调整采集任务。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值