【Springboot+JPA】存储过程Procedure使用及踩坑记录

news2025/3/29 22:44:15

Springboot+JPA存储过程调用

  • 存储过程实现
    • 1.表结构
    • 2.上报数据分页查询
      • 2.1先查出总条数
        • 2.1.1 创建存储过程
        • 2.1.2 实体类声明存储过程
        • 2.1.3 仓库方法绑定存储过程
        • 2.1.4 服务调用存储过程
      • 2.2返回分页数据
        • 2.2.1 创建存储过程
        • 2.2.2 实体类声明存储过程
        • 2.2.3 仓库方法绑定存储过程
        • 2.2.4 服务调用存储过程
    • 3.更新视频状态
      • 3.1.1 创建存储过程
      • 3.1.2 调用
    • 4.设置上报数据过期
      • 4.1.1创建存储过程
      • 4.1.2 调用
  • 存储过程调用方法
    • @Query
    • @Procedure
  • 异常处理

存储过程实现

1.表结构

本次存储过程实现功能包含两个表:
1.process_source_report 主表(简称A),记录上报数据
2.process_source_report_video 从表(简称B),记录数据关联的视频信息


/*DDL 信息*/------------

CREATE TABLE `process_source_report` (
  `process_report_id` bigint NOT NULL AUTO_INCREMENT,
  `tag` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `alarm_level` int DEFAULT NULL,
  `alarm_text` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `channel_name` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `confirm_time` datetime(6) DEFAULT NULL,
  `create_time` datetime(6) DEFAULT NULL,
  `image_file_name` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `process_id` bigint DEFAULT NULL,
  `process_name` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `source_id` bigint DEFAULT NULL,
  `source_index` int DEFAULT NULL,
  `update_time` datetime(6) DEFAULT NULL,
  `user_state` int DEFAULT '0',
  `video_file_name` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `report_status` int DEFAULT '0',
  `relative_box` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `timestamp` bigint DEFAULT NULL,
  PRIMARY KEY (`process_report_id`),
  UNIQUE KEY `UK4c7m1ir5j0uj9p4s4hyqiuh1n` (`tag`),
  KEY `IDXrp57fkk73cmvrp2c80xqskng1` (`user_state`),
  KEY `IDX7wphi9do4thvn7xqqs6f8lo7j` (`alarm_level`),
  KEY `IDXr9mb5lpy1fliw44nurlrn0bc9` (`process_id`),
  KEY `IDXanidygk5t2fmxpvutc7n28fup` (`source_id`),
  KEY `IDXldvlk8jobglhs5ytbhiks3sll` (`source_index`)
) ENGINE=InnoDB AUTO_INCREMENT=9452 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci



/*DDL 信息*/------------

CREATE TABLE `process_source_report_video` (
  `channel_area_report_video_id` bigint NOT NULL AUTO_INCREMENT,
  `channel_id` bigint DEFAULT NULL,
  `create_time` datetime(6) DEFAULT NULL,
  `pipeline_id` bigint DEFAULT NULL,
  `status` int DEFAULT NULL,
  `tag` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `timestamp_end` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `timestamp_end_by_date` datetime(6) DEFAULT NULL,
  `timestamp_start` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `timestamp_start_by_date` datetime(6) DEFAULT NULL,
  `update_time` datetime(6) DEFAULT NULL,
  `upload_status` int DEFAULT NULL,
  `upload_status_by_date` datetime(6) DEFAULT NULL,
  `video_name` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `video_path` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  PRIMARY KEY (`channel_area_report_video_id`),
  KEY `IDX165djkpsa9bp364p0qod0efrq` (`tag`)
) ENGINE=InnoDB AUTO_INCREMENT=11221 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci


2.上报数据分页查询

功能描述:表A通过多个字段进行并行分页筛选查询

2.1先查出总条数

2.1.1 创建存储过程
DROP PROCEDURE IF EXISTS channelReportPagesCount;
DELIMITER $$

CREATE
    PROCEDURE channelReportPagesCount(
	    IN p_page INT,
	    IN p_pageSize INT,
	    IN p_sourceIds VARCHAR(255),
	    IN p_processIds VARCHAR(255),
	    IN p_alarmStates VARCHAR(255),
	    IN p_alarmTypes VARCHAR(255),
	    IN p_pickDate VARCHAR(20),
	    IN p_keywords VARCHAR(255),
	    IN p_isAdmin BOOLEAN,
	    IN p_allIsNull BOOLEAN
    )
	BEGIN
		# 声明变量
		DECLARE OFFSET INT DEFAULT (p_page - 1) * p_pageSize;		
		DECLARE countQuery TEXT;
		DECLARE whereQueryJoin TEXT;
		DECLARE total_count LONG DEFAULT 0;
		
		# 计数查询语句
		SET countQuery = 'SELECT COUNT(process_report_id) into @total_count FROM process_source_report';
		# Where条件语句
		SET whereQueryJoin = ' where 1=1 ';
		
		-- Java判断是否页面传入参数都为空,如果页面参数都为空说明是在进行新告警刷新,不需要进入页面参数判断条件,节省时间
		IF p_allIsNull = FALSE THEN
			-- sourceIds 查询
			IF p_sourceIds IS NOT NULL AND p_sourceIds <> '' THEN
				SET whereQueryJoin = CONCAT(whereQueryJoin, ' AND source_id IN (', p_sourceIds, ') ');
			END IF;

			-- processIds 查询
			IF p_processIds IS NOT NULL AND p_processIds <> '' THEN
				SET whereQueryJoin = CONCAT(whereQueryJoin, ' AND process_id IN (', p_processIds, ') ');
			END IF;

			-- alarmStates 查询
			IF p_alarmStates IS NOT NULL AND p_alarmStates <> '' THEN
				SET whereQueryJoin = CONCAT(whereQueryJoin, ' AND user_state IN (', p_alarmStates, ') ');
			END IF;

			-- alarmTypes OR 查询
			IF p_alarmTypes IS NOT NULL AND p_alarmTypes <> '' THEN
				SET whereQueryJoin = CONCAT(whereQueryJoin, ' AND (alarm_text LIKE "%', REPLACE(p_alarmTypes, ',', '%" OR alarm_text LIKE "%'), '%") ');
			END IF;

			-- keywords OR 查询
			IF p_keywords IS NOT NULL AND p_keywords <> '' THEN
				SET whereQueryJoin = CONCAT(whereQueryJoin, ' AND (alarm_text LIKE "%', REPLACE(p_keywords, ',', '%" OR alarm_text LIKE "%'), '%") ');
			END IF;

			-- pickDate 日期查询
			IF p_pickDate IS NOT NULL AND p_pickDate <> '' THEN
				SET whereQueryJoin = CONCAT(whereQueryJoin, ' AND create_time >= "', p_pickDate, ' 00:00:00" AND create_time <= "', p_pickDate, ' 23:59:59" ');
			END IF;
		END IF;

		-- 管理员查看所有,非管理员只看等级为2或4的
		IF p_isAdmin = FALSE THEN
			SET whereQueryJoin = CONCAT(whereQueryJoin, ' AND (alarm_level = 2 OR alarm_level = 4) ');
		END IF;
		-- SELECT whereQueryJoin;
		
		# 拼接所有Where
		SET countQuery = CONCAT(countQuery, whereQueryJoin);
		
		SET @countQuery = countQuery;
		
		PREPARE stmtCount FROM @countQuery;  -- 加上 @ 符号
		EXECUTE stmtCount;
		DEALLOCATE PREPARE stmtCount;
		
		SET totalCount = (SELECT @total_count);
	END$$
DELIMITER ;


CALL channelReportPagesCount(
    1,        -- 页码,比如 1
    30,    -- 每页的大小,比如 10
    '',   -- 源 ID,逗号分隔的字符串,例如 '1,2,3'
    '',  -- 进程 ID,逗号分隔的字符串,例如 '4,5'
    '', -- 告警状态,逗号分隔的字符串,例如 '1,2'
    '',  -- 告警类型,逗号分隔的字符串,例如 'type1,type2'
    '',    -- 日期,例如 '2024-01-01'
    '',    -- 关键字,逗号分隔的字符串,例如 'keyword1,keyword2'
    FALSE,         -- 是否为管理员,布尔值,TRUE 或 FALSE
    TRUE
);

2.1.2 实体类声明存储过程

@NamedStoredProcedureQuery(name = "ProcessSourceReport.pagesTotalCount",
        procedureName = "channelReportPagesCount",
        parameters = {
                @StoredProcedureParameter(mode = ParameterMode.IN, name = "pageNumber", type = Integer.class),
                @StoredProcedureParameter(mode = ParameterMode.IN, name = "pageSize", type = Integer.class),
                @StoredProcedureParameter(mode = ParameterMode.IN, name = "sourceIds", type = String.class),
                @StoredProcedureParameter(mode = ParameterMode.IN, name = "processIds", type = String.class),
                @StoredProcedureParameter(mode = ParameterMode.IN, name = "alarmStates", type = String.class),
                @StoredProcedureParameter(mode = ParameterMode.IN, name = "alarmTypes", type = String.class),
                @StoredProcedureParameter(mode = ParameterMode.IN, name = "pickDate", type = String.class),
                @StoredProcedureParameter(mode = ParameterMode.IN, name = "keywords", type = String.class),
                @StoredProcedureParameter(mode = ParameterMode.IN, name = "isAdmin", type = Boolean.class),
                @StoredProcedureParameter(mode = ParameterMode.IN, name = "paramAllIsNull", type = Boolean.class)
        })
2.1.3 仓库方法绑定存储过程

 	@Procedure(name = "ProcessSourceReport.pagesTotalCount")
    BigInteger channelReportPagesCount(@Param("pageNumber") int pageNumber,
                                       @Param("pageSize") int pageSize,
                                       @Param("sourceIds") String sourceIds,
                                       @Param("processIds") String processIds,
                                       @Param("alarmStates") String alarmStates,
                                       @Param("alarmTypes") String alarmTypes,
                                       @Param("pickDate") String pickDate,
                                       @Param("keywords") String keywords,
                                       @Param("isAdmin") boolean isAdmin,
                                       @Param("paramAllIsNull") boolean paramAllIsNull);
2.1.4 服务调用存储过程
 boolean paramAllIsNull = StringUtils.isBlank(sourceIds) && StringUtils.isBlank(processIds) && StringUtils.isBlank(alarmStates)
                && StringUtils.isBlank(alarmTypes) && StringUtils.isBlank(keywords) && StringUtils.isBlank(pickDate);
BigInteger pagesTotalCount = processSourceReportRepo.channelReportPagesCount(
                pageable.getPageNumber() + 1, pageable.getPageSize(), sourceIds, processIds,
                alarmStates, alarmTypes, pickDate, keywords, isAdmin, paramAllIsNull);

2.2返回分页数据

2.2.1 创建存储过程
DROP PROCEDURE IF EXISTS channelReportPages;
DELIMITER $$

CREATE PROCEDURE channelReportPages(
	    IN p_page INT,
	    IN p_pageSize INT,
	    IN p_sourceIds VARCHAR(255),
	    IN p_processIds VARCHAR(255),
	    IN p_alarmStates VARCHAR(255),
	    IN p_alarmTypes VARCHAR(255),
	    IN p_pickDate VARCHAR(20),
	    IN p_keywords VARCHAR(255),
	    IN p_isAdmin BOOLEAN,
	    IN p_allIsNull BOOLEAN -- 所有页面查询参数是否都为空
    )
	BEGIN
		# 声明变量
		DECLARE OFFSET INT DEFAULT (p_page - 1) * p_pageSize;
		DECLARE sqlQuery TEXT;
		DECLARE whereQueryJoin TEXT;
		
		# 基本查询语句
		SET sqlQuery = 'SELECT 
		process_report_id  ,
		a.process_id ,
		a.tag,
		process_name ,
		source_id ,
		source_index ,
		channel_name ,
		alarm_text ,
		alarm_level ,
		user_state ,
		image_file_name ,
		a.create_time ,
		a.update_time ,
		video_file_name,
		(select upload_status from process_source_report_video b where b.tag = a.tag) upload_status
		FROM process_source_report a  ';
		
		# Where条件语句
		SET whereQueryJoin = ' where 1=1 ';
		
		-- Java判断是否页面传入参数都为空,如果页面参数都为空说明是在进行新告警刷新,不需要进入页面参数判断条件,节省时间
		IF p_allIsNull = FALSE THEN
			-- sourceIds 查询
			IF p_sourceIds IS NOT NULL AND p_sourceIds <> '' THEN
				SET whereQueryJoin = CONCAT(whereQueryJoin, ' AND source_id IN (', p_sourceIds, ') ');
			END IF;

			-- processIds 查询
			IF p_processIds IS NOT NULL AND p_processIds <> '' THEN
				SET whereQueryJoin = CONCAT(whereQueryJoin, ' AND process_id IN (', p_processIds, ') ');
			END IF;

			-- alarmStates 查询
			IF p_alarmStates IS NOT NULL AND p_alarmStates <> '' THEN
				SET whereQueryJoin = CONCAT(whereQueryJoin, ' AND user_state IN (', p_alarmStates, ') ');
			END IF;

			-- alarmTypes OR 查询
			IF p_alarmTypes IS NOT NULL AND p_alarmTypes <> '' THEN
				SET whereQueryJoin = CONCAT(whereQueryJoin, ' AND (alarm_text LIKE "%', REPLACE(p_alarmTypes, ',', '%" OR alarm_text LIKE "%'), '%") ');
			END IF;

			-- keywords OR 查询
			IF p_keywords IS NOT NULL AND p_keywords <> '' THEN
				SET whereQueryJoin = CONCAT(whereQueryJoin, ' AND (alarm_text LIKE "%', REPLACE(p_keywords, ',', '%" OR alarm_text LIKE "%'), '%") ');
			END IF;

			-- pickDate 日期查询
			IF p_pickDate IS NOT NULL AND p_pickDate <> '' THEN
				SET whereQueryJoin = CONCAT(whereQueryJoin, ' AND create_time >= "', p_pickDate, ' 00:00:00" AND create_time <= "', p_pickDate, ' 23:59:59" ');
			END IF;
		END IF;

		-- 管理员查看所有,非管理员只看等级为2或4的
		IF p_isAdmin = FALSE THEN
			SET whereQueryJoin = CONCAT(whereQueryJoin, ' AND (alarm_level = 2 OR alarm_level = 4) ');
		END IF;
		-- SELECT whereQueryJoin;
		
		# 拼接where
		SET sqlQuery = CONCAT(sqlQuery, whereQueryJoin);
		
		-- select sqlQuery;
		
		-- 倒序
		SET sqlQuery = CONCAT(sqlQuery, ' ORDER BY process_report_id DESC');
		
		-- 分页
		SET sqlQuery = CONCAT(sqlQuery, ' LIMIT ', OFFSET, ', ', p_pageSize);
		-- select countQuery;

		SET @sqlQuery=sqlQuery;
		
		-- 执行SQL
		PREPARE stmt FROM @sqlQuery;  -- 加上 @ 符号
		EXECUTE stmt;
		DEALLOCATE PREPARE stmt;		
	END$$
DELIMITER ;


CALL channelReportPages(
    1,        -- 页码,比如 1
    30,    -- 每页的大小,比如 10
    '',   -- 源 ID,逗号分隔的字符串,例如 '1,2,3'
    '',  -- 进程 ID,逗号分隔的字符串,例如 '4,5'
    '', -- 告警状态,逗号分隔的字符串,例如 '1,2'
    '',  -- 告警类型,逗号分隔的字符串,例如 'type1,type2'
    '',    -- 日期,例如 '2024-01-01'
    '',    -- 关键字,逗号分隔的字符串,例如 'keyword1,keyword2'
    FALSE,         -- 是否为管理员,布尔值,TRUE 或 FALSE
    TRUE
);

2.2.2 实体类声明存储过程

		@NamedStoredProcedureQuery(name = "ProcessSourceReport.pages",
        procedureName = "channelReportPages",
        parameters = {
                @StoredProcedureParameter(mode = ParameterMode.IN, name = "pageNumber", type = Integer.class),
                @StoredProcedureParameter(mode = ParameterMode.IN, name = "pageSize", type = Integer.class),
                @StoredProcedureParameter(mode = ParameterMode.IN, name = "sourceIds", type = String.class),
                @StoredProcedureParameter(mode = ParameterMode.IN, name = "processIds", type = String.class),
                @StoredProcedureParameter(mode = ParameterMode.IN, name = "alarmStates", type = String.class),
                @StoredProcedureParameter(mode = ParameterMode.IN, name = "alarmTypes", type = String.class),
                @StoredProcedureParameter(mode = ParameterMode.IN, name = "pickDate", type = String.class),
                @StoredProcedureParameter(mode = ParameterMode.IN, name = "keywords", type = String.class),
                @StoredProcedureParameter(mode = ParameterMode.IN, name = "isAdmin", type = Boolean.class),
                @StoredProcedureParameter(mode = ParameterMode.IN, name = "paramAllIsNull", type = Boolean.class)
        })
2.2.3 仓库方法绑定存储过程
@Procedure(name = "ProcessSourceReport.pages")
    List<Object[]> channelReportPages(@Param("pageNumber") int pageNumber,
                                      @Param("pageSize") int pageSize,
                                      @Param("sourceIds") String sourceIds,
                                      @Param("processIds") String processIds,
                                      @Param("alarmStates") String alarmStates,
                                      @Param("alarmTypes") String alarmTypes,
                                      @Param("pickDate") String pickDate,
                                      @Param("keywords") String keywords,
                                      @Param("isAdmin") boolean isAdmin,
                                      @Param("paramAllIsNull") boolean paramAllIsNull);
2.2.4 服务调用存储过程
new PageImpl<>(channelReportPages(pageable.getPageNumber() + 1, pageable.getPageSize(), sourceIds, processIds,
                alarmStates, alarmTypes, pickDate, keywords, isAdmin, paramAllIsNull).stream().map(result -> {
            return new StreamReportBO(((BigInteger) result[0]).longValue(), // processReportId, bigint
                    ((BigInteger) result[1]).longValue(), // processId, bigint
                    (String) result[2],                // tag
                    (String) result[3],                // processName
                    ((BigInteger) result[4]).longValue(), // channelId, bigint
                    ((Integer) result[5]), // channelIndex, int
                    (String) result[6],                // channelName
                    (String) result[7],                // alarmText
                    ((Integer) result[8]),  // alarmLevel, int
                    ((Integer) result[9]),  // userState, int
                    (String) result[10],               // imageFileName
                    (Date) result[11],                 // createTime
                    (Date) result[12],                 // updateTime
                    (String) result[13], // roiFileName
                    (Integer) result[14]);// uploadStatus
        }).toList(), pageable, pagesTotalCount.longValue());

3.更新视频状态

3.1.1 创建存储过程

DROP PROCEDURE IF EXISTS videoUploadEnd;
DELIMITER $$

CREATE
    PROCEDURE videoUploadEnd(
	IN p_video_name VARCHAR(256)
    )
	BEGIN
	    DECLARE EXIT HANDLER FOR SQLEXCEPTION
	    BEGIN
		-- 错误处理
		ROLLBACK;
	    END;

	    START TRANSACTION;

	    -- 更新主表中的状态
	    UPDATE process_source_report_video
	    SET upload_status = 1, upload_status_by_date = NOW()
	    WHERE video_name = p_video_name; -- 根据实际需要更新的条件

	    -- 返回关联表中的数据
	    SELECT  process_id, process_report_id, alarm_level, image_file_name, video_file_name, tag, alarm_text
	    FROM process_source_report 
	    WHERE video_file_name = p_video_name; -- 只返回刚更新的相关数据

	    COMMIT;
	END$$
DELIMITER ;

3.1.2 调用

// repo 层

@Modifying
@Procedure(name = "ProcessSourceReportVideo.videoUploadEnd")
List<Object[]> VideoUploadEnd(String videoName);


// Service层
public List<VideoUploadEndVO> updateVideoUploadStatusAndReturnReportData(String videoName) {
        List<Object[]> objects = processSourceReportVideoRepo.VideoUploadEnd(videoName);
        if (null == objects || objects.isEmpty()) {
            return null;
        }
        return objects.stream().map(item ->
                new VideoUploadEndVO(((BigInteger) item[0]).longValue(), ((BigInteger) item[1]).longValue(), (Integer) item[2], (String) item[3], (String) item[4], (String) item[5], (String) item[6])).toList();
    }

4.设置上报数据过期

4.1.1创建存储过程

DROP PROCEDURE IF EXISTS setReportDataExpire;
DELIMITER $$

CREATE
    PROCEDURE setReportDataExpire()
	BEGIN
	    DECLARE EXIT HANDLER FOR SQLEXCEPTION
	    BEGIN
		-- 错误处理
		ROLLBACK;
	    END;

	     -- 设置共用变量
	    SET @expiration_time = SUBDATE(NOW(), INTERVAL 10 MINUTE);
	    SET @nowTime = NOW();

	    START TRANSACTION;
	    
	    -- 更新主表中的状态
	    UPDATE process_source_report
	    SET user_state = 2, confirm_time = @nowTime
	    WHERE user_state = 0 AND create_time < @expiration_time; -- 根据实际需要更新的条件
	    
	    -- 更新视频状态,漏网之鱼
	    UPDATE process_source_report_video 
	    SET upload_status = 1, upload_status_by_date = NOW() 
	    WHERE tag IN (SELECT tag
	    FROM process_source_report 
	    WHERE confirm_time = @nowTime);

	    -- 返回关联表中的数据
	    SELECT  process_id, process_report_id, alarm_level
	    FROM process_source_report 
	    WHERE confirm_time = @nowTime; -- 只返回刚更新的相关数据

	    COMMIT;
	END$$
DELIMITER ;

4.1.2 调用


// repo 层
@Modifying
@Procedure(name = "ProcessSourceReport.setReportDataExpire")
List<Object[]> setReportDataExpireProcedure();

// service层
public List<ProcessReportStatusChangeVO> setReportDataExpireProcedure() {
        List<Object[]> objects = processSourceReportRepo.setReportDataExpireProcedure();
        if (null == objects || objects.isEmpty()) {
            return null;
        }
        return objects.stream().map(item ->
                new ProcessReportStatusChangeVO(((BigInteger) item[0]).longValue(), ((BigInteger) item[1]).longValue(), (Integer) item[2])).toList();
    }

存储过程调用方法

以下两种方法都可以调用上文的存储过程,任选一种,注意区分这里@Query用到的是数据库实际存储过程名称,@Procedure用的则是实体类里面定义的名称

@Query

 @Query(value = "CALL channelReportPagesCount(?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10)", nativeQuery = true)
 
 @Query(value = "CALL channelReportPages(?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10)", nativeQuery = true)

@Procedure

如上文2.x.3所示

异常处理

运行时异常:Positional parameter [1] is not registered with this procedure call; nested exception is java.lang.IllegalArgumentException: Positional parameter [1] is not registered with this procedure call
org.springframework.dao.InvalidDataAccessApiUsageException: Positional parameter [1] is not registered with this procedure call; nested exception is java.lang.IllegalArgumentException: Positional parameter [1] is not registered with this procedure call
at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:374)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:235)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:551)

Caused by: java.lang.IllegalArgumentException: Positional parameter [1] is not registered with this procedure call
at org.hibernate.query.procedure.internal.ProcedureParameterMetadata.getQueryParameter(ProcedureParameterMetadata.java:141)

出现以上异常需要着重检查
@StoredProcedureParameter(mode = ParameterMode.IN, name = “pageNumber”, type = Integer.class)这里的name和repo方法里面写的一致,如果还是报错,一定要在repo方法参数名前加上@Param(“”)注解

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

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

相关文章

【江协科技STM32】软件SPI读写W25Q64芯片(学习笔记)

SPI通信协议及S为5Q64简介&#xff1a;【STM32】SPI通信协议&W25Q64Flash存储器芯片&#xff08;学习笔记&#xff09;-CSDN博客 STM32与W25Q64模块接线&#xff1a; SPI初始化&#xff1a; 片选SS、始终SCK、MOSI都是主机输出引脚&#xff0c;输出引脚配置为推挽输出&…

Git+Fork 入门介绍

git 分区理解 fork安装 从路径下去拿软件时&#xff0c;注意先拉到本地。经验来看&#xff0c;fork直接安装会出不可思议的问题。 fork操作 安装&#xff0c;注意设置好名字&#xff0c;如果之前安装的同学&#xff0c;名字没有写好&#xff0c;重新安装设置好名字。 clone操…

Windows系统安装Node.js和npm教程【成功】

0.引言——Node.js和npm介绍 项目描述Node.js基于Chrome V8引擎的JavaScript运行环境&#xff0c;使JavaScript可用于服务器端开发。采用单线程、非阻塞I/O及事件驱动架构&#xff0c;适用于构建Web服务器、实时应用和命令行工具等npmNode.js的包管理器与大型软件注册表。拥有…

Axure RP9.0 教程:左侧菜单列表导航 ( 点击父级菜单,子菜单自动收缩或展开)【响应式的菜单导航】

文章目录 引言I 实现步骤添加商品管理菜单组推拉效果引言 应用场景:PC端管理后台页面,左侧菜单列表导航。 思路: 用到了动态面板的两个交互效果来实现:隐藏/显示切换、展开/收起元件向下I 实现步骤 添加商品管理菜单组 在左侧画布区域添加一个菜单栏矩形框;再添加一个商…

科技赋能|ZGIS综合管网智能管理平台守护地下城市生命线

地下管网作为城市公共安全的重要组成部分&#xff0c;担负着城市的信息传递、能源输送、排涝减灾等重要任务&#xff0c;是维系城市正常运行、满足群众生产生活需要的重要基础设施&#xff0c;是城市各功能区有机连接和运转的维系&#xff0c;因此&#xff0c;也被称为城市“生…

如何保证LabVIEW软件开发的质量?

LabVIEW作为图形化编程工具&#xff0c;广泛应用于工业测控、自动化测试等领域。其开发模式灵活&#xff0c;但若缺乏规范&#xff0c;易导致代码可读性差、维护困难、性能低下等问题。保证LabVIEW开发质量需从代码规范、模块化设计、测试验证、版本管理、文档完善等多维度入手…

如何快速解决 Postman 报错?

介绍一些 Postman 常见的报错与处理方法&#xff0c;希望能够对大家有所帮助。 Postman 一直转圈打不开的问题 Postman 报错处理指南&#xff1a;常见报错与解决方法

C++ 多线程简要讲解

std::thread是 C11 标准库中用于多线程编程的核心类&#xff0c;提供线程的创建、管理和同步功能。下面我们一一讲解。 一.构造函数 官网的构造函数如下&#xff1a; 1.默认构造函数和线程创建 thread() noexcept; 作用&#xff1a;创建一个 std::thread 对象&#xff0c;但…

如何设计一个处理物联网设备数据流的后端系统。

一、系统架构设计 物联网设备数据流的后端系统通常包括以下几个主要组件: ①设备数据采集层:负责从物联网设备收集数据。 ②数据传输层:负责将设备数据传输到后端系统。 ③数据处理层:实时或批量处理传输到后的数据。 ④存储层:负责存储设备数据。 ⑤API层:提供外部…

深入理解 Spring Boot 应用的生命周期:从启动到关闭的全流程解析

引言 Spring Boot 是当今 Java 开发中最流行的框架之一&#xff0c;它以简化配置和快速开发著称。然而&#xff0c;要真正掌握 Spring Boot&#xff0c;理解其应用的生命周期是至关重要的。本文将深入探讨 Spring Boot 应用的生命周期&#xff0c;从启动到关闭的各个阶段&…

【算法笔记】图论基础(一):建图、存图、树和图的遍历、拓扑排序、最小生成树

目录 何为图论图的概念 图的一些基本概念有向图和无向图带权图连通图和非连通图对于无向图对于有向图 度对于无向图对于有向图一些结论 环自环、重边、简单图、完全图自环重边简单图 稀疏图和稠密图子图、生成子图同构 图的存储直接存边邻接矩阵存边邻接表存边链式前向星存边 图…

SpringMVC 请求与响应处理详解

引言 在 Java Web 开发中&#xff0c;SpringMVC 作为 Spring 框架的重要模块&#xff0c;提供了强大的请求和响应处理机制。本文将深入探讨 SpringMVC 中请求和响应的处理方式&#xff0c;结合实际案例&#xff0c;帮助开发者更好地理解和应用这些功能。 一、SpringMVC 请求处…

【python】requests 爬虫高效获取游戏皮肤图

1. 引言 在当今的数字时代&#xff0c;游戏已经成为许多人生活中不可或缺的一部分。而游戏中的皮肤&#xff0c;作为玩家个性化表达的重要方式&#xff0c;更是受到了广泛的关注和喜爱。然而&#xff0c;对于许多玩家来说&#xff0c;获取游戏皮肤往往需要花费大量的时间和精力…

(UI自动化测试web端)第二篇:元素定位的方法_css定位之ID选择器

看代码里的【find_element_by_css_selector( )】( )里的表达式怎么写&#xff1f; 文章介绍了第一种写法id选择器&#xff0c;其实XPath元素定位要比CSS好用&#xff0c;原因是CSS无法使用下标&#xff08;工作当中也是常用的xpath&#xff09;&#xff0c;但CSS定位速度比XPat…

23种设计模式-代理(Proxy)设计模式

代理设计模式 &#x1f6a9;什么是代理设计模式&#xff1f;&#x1f6a9;代理设计模式的特点&#x1f6a9;代理设计模式的结构&#x1f6a9;代理设计模式的优缺点&#x1f6a9;代理设计模式的Java实现&#x1f6a9;代码总结&#x1f6a9;总结 &#x1f6a9;什么是代理设计模式…

【react18】react项目使用mock模拟后台接口

前后端分离项目&#xff0c;后端还没有接口的时候&#xff0c;前端可以使用mockjs的技术实行假数据的模拟。这里使用的是mock的库msw实现这个业务. MSW msw是mock的工具&#xff0c;官网地址是在这里 使用步骤 1.安装msw npm install mswlatest --save-dev2.新建存放mock接…

Windows下VSCode的安装

前言 VSCode的安装看起来平平无奇&#xff0c;但也不是轻轻松松的。笔者将最新的Windows下安装VSCode&#xff0c;以及运行最简单的C程序的过程记录下来&#xff0c;供后续的自己和大家参考。 一、官网下载安装包 Visual Studio Code - Code Editing. Redefined 二、安装 直接…

django入门教程之templates和static资源【五】

使用app01子应用举例说明模板的使用。templates官方文档。 templates完整流程认知 第一步&#xff0c;在settings.py中注册app01子应用。 第二步&#xff0c;在app01目录下&#xff0c;新建templates和static目录&#xff0c;用于存放模板文件和资源文件。目录结构如下&#…

【区块链安全 | 第一篇】密码学原理

文章目录 1.哈希函数1.1 哈希函数的性质1.2 常见哈希算法1.3 Merkle Tree&#xff08;默克尔树&#xff09;1.4 HMAC&#xff08;哈希消息认证码&#xff09; 2. 公钥密码学2.1 对称加密 vs 非对称加密2.2 RSA 算法2.3 ECC&#xff08;椭圆曲线密码学&#xff09;2.4 Diffie-He…

Linux安装MySQL数据库并使用C语言进行数据库开发

目录 一、前言 二、安装VMware运行Ubuntu 1.安装VMware 2.使用VMware打开Ubuntu 三、配置VMware使用网卡 1.添加NAT网卡 四、Linux下安装MySQL数据库 五、安装MySQL开发库 六、演示代码 sql_connect.c sql_connect.h main.c中数据库相关代码 结尾 一、前言 由于最…