MYBATIS: Use Oracle Function

本文详细解析了使用MyBatis调用Oracle Function过程中遇到的bug,包括参数处理、Mapper配置以及Service调用的注意事项。通过实例演示了正确的参数传递方式,并解释了MyBatis如何自动处理返回值。

今天遇到一个bug, mybatis 调用oracle的function,总结几点如下:

1.function的参数是没有out 参数的,举例如下:

FUNCTION get_result(p1 IN VARCHAR2, p2 IN VARCHAR2)
    RETURN NUMBER IS
    result table1.somecolumn%TYPE;
  BEGIN
    IF (p2= '01') THEN
           UPDATE table1 t
         SET t.somecolumn= CASE WHEN somecolumn>= 127 OR  somecolumn IS NULL THEN 1 ELSE  somecolumn+1 END
WHERE t1.keyColumn= p1 RETURNING
somecolumn INTO result;
    ELSIF (p2= '02') THEN    
      UPDATE table1
         SET somecolumn= CASE WHEN somecolumn>= 15 OR somecolumn IS NULL THEN 0 ELSE somecolumn+1 END
       WHERE table1.keyColumn= p1
      RETURNING somecolumn INTO result;
    END IF;
    COMMIT;
    RETURN reslult;
  END get_result
;


<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">2.针对oracle function , mybatis的mapper,不要设置out参数,没必要.正确的方式举例如下:</span>

 <select id="procedule_getxxResult" parameterType="java.util.Map"  statementType="CALLABLE">
			{
			  #{result,mode=OUT,jdbcType=NUMERIC,javaType=Integer} = call pkg_services.get_result(
					#{p1,mode=IN,jdbcType=VARCHAR},
					#{p2,mode=IN,jdbcType=VARCHAR}
				)
			}
	</select>


3.service中,调用时,传入参数的Map中,不需要设定输出的字段,mybatis会自动将该返回值存在Map中,key为result(以此例子为准)

<span style="font-size:14px;">public int getxxxSeq(String p1,String p2){
		Map<String,Object> map = new HashMap<String,Object>(4);
		map.put("p_zdljdz", strRtua);
		map.put("p_zdgylx", rtuPotocType);
		
		try{
			testMapper.<span style="font-family: Arial, Helvetica, sans-serif;">procedule_getxxResult</span><span style="font-family: Arial, Helvetica, sans-serif;">(map);</span>
			String res= map.get("result").toString();
			Integer value =  Integer.valueOf(</span><span style="font-family: Arial, Helvetica, sans-serif; font-size: 14px;">res</span><span style="font-family: Arial, Helvetica, sans-serif;">);</span><span style="font-size:14px;">
			return value;
		}catch(Exception e){
			System.out.println(e.getLocalizedMessage());
		}
		return -1;
	}</span>


到此,上面几点完整后就OK了~


前端配置const path = require('path') function resolve(dir) { return path.join(__dirname, dir) } function publicPath() { return process.env.NODE_ENV === 'production' ? './' : '/' } module.exports = { publicPath: publicPath(), configureWebpack: { resolve: { alias: { '@': resolve('src') }, fallback: { path: require.resolve('path-browserify'), fs: require.resolve('browserify-fs'), os: require.resolve('os-browserify/browser'), timers: require.resolve('timers-browserify'), buffer: require.resolve('buffer'), stream: require.resolve('stream-browserify') } } }, lintOnSave: false, devServer: { proxy: { '/springbootw12d6cw5': { target: 'http://192.168.1.15:9090', // ✅ 只写主机 changeOrigin: true, secure: false, pathRewrite: { '^/springbootw12d6cw5': '/springbootw12d6cw5' // ✅ 保持上下文路径 } } } }, chainWebpack(config) { config.module .rule('svg') .exclude.add(resolve('src/icons')) .end() config.module .rule('icons') .test(/\.svg$/) .include.add(resolve('src/icons')) .end() .use('svg-sprite-loader') .loader('svg-sprite-loader') .options({ symbolId: 'icon-[name]' }) .end() } } 后端配置# Tomcat server: tomcat: uri-encoding: UTF-8 port: 9090 address: 0.0.0.0 servlet: context-path: /springbootw12d6cw5 spring: datasource: driverClassName: com.mysql.cj.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/db_creamics?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8&useSSL=false&allowPublicKeyRetrieval=true username: root password: root # driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver # url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=springbootw12d6cw5 # username: sa # password: 123456 servlet: multipart: max-file-size: 300MB max-request-size: 300MB #mybatis mybatis-plus: mapper-locations: classpath*:mapper/*.xml #实体扫描,多个package用逗号或者分号分隔 typeAliasesPackage: com.entity global-config: #主键类型 0:"数据库ID自增", 1:"用户输入ID",2:"全局唯一ID (数字类型唯一ID)", 3:"全局唯一ID UUID"; id-type: 1 #字段策略 0:"忽略判断",1:"非 NULL 判断"),2:"非空判断" field-strategy: 1 #驼峰下划线转换 db-column-underline: true #刷新mapper 调试神器 refresh-mapper: true #逻辑删除配置 logic-delete-value: -1 logic-not-delete-value: 0 #自定义SQL注入器 sql-injector: com.baomidou.mybatisplus.mapper.LogicSqlInjector configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl map-underscore-to-camel-case: true cache-enabled: false call-setters-on-nulls: true #springboot 项目mybatis plus 设置 jdbcTypeForNull (oracle数据库需配置JdbcType.NULL, 默认是Other) jdbc-type-for-null: 'null' logging: level: com.tc.mapper: debug pattern: dateformat: MM-dd HH:mm:ss:SSS,nginx配置#user nobody; worker_processes 1; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; server { listen 80; server_name localhost; # 前端项目根目录 location / { root F:/www/myapp; index index.html; try_files $uri $uri/ /index.html; # 支持 Vue history 模式 } # 代理后端 Spring Boot 接口 # ✅ 将 error_page 引用的 location 移入 server 内部 error_page 500 502 503 504 /50x.html; location = /50x.html { root html; # 默认指向 nginx/html 目录下的 50x.html } } # === 可选:其他虚拟主机或 HTTPS server === # server { # listen 8000; # server_name somename; # ... # } # server { # listen 443 ssl; # server_name localhost; # ssl_certificate cert.pem; # ssl_certificate_key cert.key; # ... # } } 外网访问失败
最新发布
09-19
你已经完成了 **Vue 前端 + Spring Boot 后端 + Nginx 反向代理** 的完整配置,本地开发和打包部署也看似正常,但 **外网无法访问**。 我们来从整体架构出发,逐层排查问题。你的三大组件配置基本正确,但关键在于:**Nginx 的反向代理规则在 `nginx.conf` 中被注释掉了!** --- ## 🔴 根本原因:**Nginx 配置中缺失了对后端的代理规则** 你在 `nginx.conf` 中写了一半: ```nginx # 代理后端 Spring Boot 接口 ``` ✅ 这一行之后的内容(`location /springbootw12d6cw5/ { ... }`)**不见了!** 也就是说: 👉 所有请求 `/springbootw12d6cw5/xxx` 都会被当作静态资源查找,找不到就返回 `index.html` 或 404! --- ## ✅ 正确的 `nginx.conf` 应该包含如下完整代理规则 请将以下内容补全到你的 `nginx.conf` 文件中: ```nginx #user nobody; worker_processes 1; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; server { listen 80; server_name localhost; # 前端项目根目录 location / { root F:/www/myapp; index index.html; try_files $uri $uri/ /index.html; # 支持 Vue history 模式 } # ✅ 重要:代理后端 Spring Boot 接口 location /springbootw12d6cw5/ { proxy_pass http://192.168.1.15:9090/springbootw12d6cw5/; # 保留客户端真实信息 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_http_version 1.1; proxy_buffering off; proxy_cache off; # 处理预检请求(CORS) if ($request_method = 'OPTIONS') { add_header Access-Control-Allow-Origin "*"; add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"; add_header Access-Control-Allow-Headers "Content-Type, Authorization"; return 204; } # 添加 CORS 响应头 add_header Access-Control-Allow-Origin "*" always; add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS" always; add_header Access-Control-Allow-Headers "Content-Type, Authorization" always; } # 错误页面 error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } } ``` > ⚠️ 特别注意: > - `location /springbootw12d6cw5/` 必须存在 > - `proxy_pass` 地址要带上下文路径 `/springbootw12d6cw5/` > - 斜杠 `/` 要对齐,否则路径拼接错误 --- ## ✅ 确认其他关键点是否满足(缺一不可) | 条件 | 是否满足 | 检查方法 | |------|----------|---------| | ✅ 1. Spring Boot 正常运行 | ☐ | 访问 `http://192.168.1.15:9090/springbootw12d6cw5/hello` 是否返回数据? | | ✅ 2. Nginx 正常启动且无语法错误 | ☐ | 运行 `nginx.exe -t` 测试配置 | | ✅ 3. Nginx 监听了 80 端口 | ☐ | `netstat -ano \| findstr :80` 查看 LISTENING | | ✅ 4. Windows 防火墙放行 80 端口 | ☐ | PowerShell 添加入站规则 | | ✅ 5. 路由器做了 80 → 192.168.1.15:80 的端口转发 | ☐ | 登录路由器设置 NAT 映射 | | ✅ 6. 你拥有公网 IP(非 CGNAT) | ☐ | 对比 [ip.cn](https://ip.cn) 和路由器 WAN IP | | ✅ 7. 运营商未封禁 80 端口 | ☐ | 尝试改用 `listen 8080;` 测试 | --- ## 🧪 测试步骤清单(建议按顺序执行) ### 第一步:本地测试(确保基础服务正常) 1. 启动 Spring Boot 项目 2. 启动 Nginx 3. 浏览器访问: - `http://localhost/` → 应显示前端页面 ✔️ - `http://localhost/springbootw12d6cw5/user/list` → 应返回 JSON 数据 ✔️ > 如果这一步失败 → 先解决本地代理问题 --- ### 第二步:局域网内测试(验证 Nginx 是否可被访问) 用手机或其他电脑连接同一 WiFi: ```text http://192.168.1.15/ ``` ✅ 成功加载前端 → 说明 Nginx 正常对外提供服务 --- ### 第三步:外网测试(终极目标) 使用手机 4G/5G 网络访问: ```text http://你的公网IP/ ``` 📌 如何获取“你的公网IP”? - 访问 [https://ip.cn](https://ip.cn) 查看当前公网出口 IP #### ❌ 如果打不开? ##### 方案一:换端口测试(绕过运营商封锁) 修改 Nginx 监听为 `8080`: ```nginx listen 8080; ``` 然后重启 Nginx: ```bash nginx.exe -s reload ``` 并在路由器做端口映射: | 外部端口 | 内部IP | 内部端口 | |--------|--------|---------| | 8080 | 192.168.1.15 | 8080 | 再从外网访问: ``` http://你的公网IP:8080/ ``` ✅ 成功能说明是 **运营商封了 80 端口** --- ### 第四步:使用内网穿透(推荐给家庭宽带用户) 由于大多数家庭宽带没有公网 IP 且 80/443 被封,建议使用 **内网穿透工具**。 #### ✅ 推荐方案:[localtunnel](https://theboroer.github.io/localtunnel-www/) ```bash # 安装 npm install -g localtunnel # 暴露本地 80 端口 lt --port 80 ``` 输出类似: ``` your url is: https://abcd1234.loca.lt ``` 然后分享这个链接即可让外网访问你的系统! --- ## 💡 补充说明:`vue.config.js` 的作用范围 你配置的 `devServer.proxy` 是 **仅用于开发环境**(`npm run serve`),生产环境下不起作用。 ✅ 生产环境的代理必须由 Nginx 实现! 所以你现在的情况是: | 环境 | 代理由谁处理 | |------|-------------| | 开发环境 (`npm run serve`) | Vue DevServer 代理 | | 生产环境 (`npm run build` + Nginx) | Nginx 代理 | 因此你不能依赖 `vue.config.js` 来实现外网访问! --- ## ✅ 最终总结 ### 🔴 当前失败主因: > **`nginx.conf` 中缺少 `location /springbootw12d6cw5/` 代理规则!** ### ✅ 解决方案: 1. ✅ 补全 Nginx 代理配置 2. ✅ 检查防火墙、端口转发、公网 IP 3. ✅ 使用 `localtunnel` 或 `frp` 实现外网访问(适合无公网 IP 用户) --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值