ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

SqlRest 1.6实战:PostgreSQL下SQL直连REST接口配置指南

SqlRest 1.6实战:PostgreSQL下SQL直连REST接口配置指南 做后端的人基本都遇到过这种需求前端要一个列表、一个下拉框或者一个报表数据。如果每次都写一套 Controller、Service、Mapper小项目还好接口一多就真的烦。今天要聊的 SqlRest 1.6就是专门对付这种需求的——它把 SQL 直接映射成 REST 接口数据库查询完直接通过 HTTP 返回等于把写接口这件事简化成写 SQL。这篇文章记录的是我在 IDEA 里把 SqlRest 1.6 的 pg 版PostgreSQL完整跑起来的过程从环境准备、项目导入、数据源配置到启动验证都有最后还有我踩过的几个坑。不管你是想把 SqlRest 接进自己的项目还是单纯想看看这个开源方案到底能不能用都可以照着走一遍。1. SqlRest到底是个什么东西1.1 一句话理解它的核心机制SqlRest 的核心思路你可以理解成把 SQL 文件当接口定义。传统方式里要出一个用户列表接口你得经历建 Mapper、写 XML、写 Service、写 Controller、处理参数校验、包装返回结构……至少六个步骤。而 SqlRest 的做法是你只需要在一个 SQL 文件里写好这条查询给它起个名字然后在 HTTP 请求里用这个名字去调用它。框架帮你完成参数解析、SQL 动态拼接、数据库查询、结果集序列化、分页处理一条龙。这种设计解决的实际问题非常明确接口开发周期大幅缩短临时提数、报表查询、BI 看板这类场景尤其适合。变更成本极低。SQL 改了不用重新发布整个应用因为接口只是 SQL 的一个映射。对前端友好。前端只需要知道接口名 参数不用关心 SQL 长什么样。弱化后端编码门槛。很多纯 SQL 能解决的问题不需要再靠 Java 代码绕一圈。当然它不是万能的。它更适合查询为主、逻辑简单、变更频繁的数据服务场景。如果你的接口里有复杂的业务校验、事务、消息推送那还是老老实实写业务代码。1.2 为什么选择 pg 版标题里特意标注了pg 版说明这个版本是面向 PostgreSQL 的。很多开源项目默认演示用的是 MySQL切到 pg 之后最大的几个差异点在这里差异点MySQL 习惯PostgreSQL 习惯JDBC 驱动com.mysql.cj.jdbc.Driverorg.postgresql.DriverURL 格式jdbc:mysql://localhost:3306/dbjdbc:postgresql://localhost:5432/db分页写法LIMIT ?, ?LIMIT ? OFFSET ?schema 概念库.表库.schema.表默认 public自增主键AUTO_INCREMENTSERIAL / IDENTITY返回更新行手动处理RETURNING 子句pg 版在 SqlRest 里主要体现为驱动选择、SQL 方言模板、以及一些类型映射上的适配。比如 pg 的 boolean 类型、jsonb 类型和 MySQL 的 tinyint、json 返回出来的 Java 类型是不一样的在结果序列化时要特别注意。1.3 适合谁来读这篇如果你属于下面任意一类这篇文章可以直接照着操作想快速把 SqlRest 1.6 跑起来验证一下效果的人。项目用的是 PostgreSQL但网上教程大多是 MySQL切过来总是报错的人。对SQL 即接口这种轻量数据服务方案感兴趣想看看它到底够不够用的人。接下来按我的实际操作顺序从零开始搭一遍。2. 环境准备一步都不能省2.1 基础软件版本清单我把整个环境列个表直接用我这套组合基本不会出问题软件版本建议说明JDK1.8 或 11SqlRest 1.6 基于 Spring Boot 2.xJDK 8 最稳妥JDK 11 也没问题Maven3.6.x 及以上依赖管理IDEA 内置的可能不够用最好配自己装的IDEA2020.3 以上我本地用的 IDEA 2023.1社区版也可以PostgreSQL12 及以上我本地用的 14.5pgAdmin / DBeaver随意建库建表用命令行党可以跳过这里有个容易踩的坑IDEA 自带的 Maven 和外部 Maven 混用。如果你本地已经装了 Maven建议在 IDEA 的 Settings → Build Tools → Maven 里把 Maven home path 指到你自己的那个同时确认 JDK 版本统一。版本不一致最典型的表现就是项目导入后依赖报错、编译级别不对。2.2 检查 Java 和 Maven 环境在终端里跑两条命令确认一下java -version mvn -versionJava 版本没问题后确认 Maven 的 settings.xml 里有国内镜像。SqlRest 依赖的 Spring Boot 全家桶不算多但第一次下载还是要花点时间没有镜像的话有些包会非常慢。我直接在全局 settings.xml 里加了阿里云镜像mirror idaliyunmaven/id mirrorOf*/mirrorOf name阿里云公共仓库/name urlhttps://maven.aliyun.com/repository/public/url /mirror这个步骤很多人忽略等到 IDEA 导入项目时卡在下载依赖才回头补纯浪费时间。2.3 安装并初始化 PostgreSQLPostgreSQL 安装完成后第一件事是设置 postgres 用户的密码并确认服务在监听 5432 端口。这一步没法跳过因为后面 application.yml 里要写连接信息。我习惯用命令行建库比点界面快# 进入 psql 命令行 psql -U postgres # 创建测试库 CREATE DATABASE sqlrest_demo; # 建一个 schema可选默认用 public 就行 CREATE SCHEMA IF NOT EXISTS demo; # 切换库 \c sqlrest_demo记两点第一pg 12 之后默认认证方式通常是 scram-sha-256只要密码设置正确从 Java 连接一般不会出问题万一报认证失败要检查 pg_hba.conf 里的规则。第二一定要确认端口是 5432如果本机装了多个 pg 实例很容易连到旧实例上后面排错会很头疼。2.4 准备测试表数据我用一个简单的用户表来验证。注意 pg 的建表语法主键用 SERIAL字符串用 varchar时间字段用 timestampCREATE TABLE t_user ( id SERIAL PRIMARY KEY, name VARCHAR(64) NOT NULL, age INT, email VARCHAR(128), status SMALLINT DEFAULT 1, create_time TIMESTAMP DEFAULT now() ); INSERT INTO t_user (name, age, email, status) VALUES (张三, 25, zhangsandemo.com, 1), (李四, 30, lisidemo.com, 1), (王五, 22, wangwudemo.com, 0);插入几条数据后用SELECT * FROM t_user;验证一下。如果这里查不出来后面接口一定也查不出来。先确认底层数据没问题再往上走。3. 获取 SqlRest 1.6 源码并在 IDEA 中导入3.1 从开源仓库拉取项目SqlRest 项目一般托管在 Gitee / GitHub 上直接搜索SqlRest或者找官方主页的仓库地址。这里不贴具体地址了因为仓库链接可能会有变动。你自己搜的时候注意一点版本号要选 1.6 的 tag 或分支不要直接拉 master/main那可能是新版本的开发分支结构和配置项可能已经不一样了。用命令行拉取后切到 1.6 对应版本git clone 仓库地址 sqlrest-1.6 cd sqlrest-1.6 git tag # 查看有哪些 tag git checkout v1.6如果没有合适的 tag就选一个发布时间对应 1.6 的 commit。这一步很重要SqlRest 后面的版本配置文件格式变过好几次你照着 1.6 的教程去配新版很容易对不上。3.2 IDEA 导入 Maven 项目IDEA 里导入 Maven 项目的标准动作打开 IDEA选 Open找到刚才 clone 下来的目录选择里面的 pom.xml。选择 Open as ProjectIDEA 会自动识别为 Maven 项目。等待右下角的 Maven 依赖导入完成。第一次可能耗时几分钟注意看状态栏进度条。导入后检查 Project StructureFile → Project Structure → Project → Project SDK选你本地的 JDK 8 或 11。检查 Language level通常保持默认如果报语法错误设置为 8。Modules 里确认 SqlRest 的模块已经识别为 Maven 模块。一个非常常见的问题是IDEA 导入后出现一堆Cannot resolve symbol红色报错多半是 Maven 依赖没有正确下载完。解决办法是右侧 Maven 面板点刷新Reload All Maven Projects如果还不行在终端执行mvn -U clean compile强制更新快照依赖。3.3 项目结构快速认知导入后你不需要一下子看懂所有代码但是下面几个关键位置要知道sqlrest-1.6 ├── pom.xml # 父工程声明依赖版本 ├── sqlrest-core # 核心模块SQL 解析、接口路由、执行引擎 ├── sqlrest-spring-boot-starter # 与 Spring Boot 集成的自动配置模块 ├── sqlrest-demo # 示例工程通常包含启动类和配置文件 │ └── src/main/resources │ ├── application.yml # 核心配置 │ └── sqls/ # SQL 映射文件目录有些版本叫 sqlrest └── README.md重点看 demo 模块尤其是它的 application.yml这就是我们要改的地方。有些版本把 demo 单独作为模块IDEA 里右键 demo 模块的启动类直接运行即可不需要运行整个父工程。4. 核心配置把 pg 数据源接进来4.1 application.yml 数据源配置这是整个启动过程中最容易出问题的地方。我直接给出一个可用的 pg 配置server: port: 8080 spring: datasource: driver-class-name: org.postgresql.Driver url: jdbc:postgresql://localhost:5432/sqlrest_demo username: postgres password: postgres hikari: maximum-pool-size: 10 minimum-idle: 2 sqlrest: enabled: true # SQL 映射文件所在目录相对 classpath sql-file-path: sqls/ # 接口前缀通过 /sql/xxx 访问 request-path-prefix: /sql # 是否打印 SQL 日志 show-sql: true几个关键点driver-class-name必须是org.postgresql.Driver不是 MySQL 的驱动。这看起来像是废话但很多人从 MySQL 迁移过来就是卡在这一行。URL 里sqlrest_demo是数据库名要和你建库时完全一致。pg 的 URL 不需要加useSSL、serverTimezone这些 MySQL 参数别把 MySQL 的习惯带过来。sql-file-path配置的是 SQL 文件的存放目录这个路径是最容易配置错的下面会单独讲。HikariCP 连接池参数按需调整。如果数据库和 Spring Boot 应用在同一台机器maximum-pool-size设置为 10 就够用了别上来就配 100没必要反而增加数据库的连接负担。4.2 动态 SQL 文件应该怎么写SqlRest 的 SQL 文件不是普通 SQL它有自己的格式约定。以 1.6 为例我用的格式是这样[query:userList] SELECT u.id, u.name, u.age, u.email, u.status FROM t_user u WHERE 1 1 [#if name] AND u.name LIKE CONCAT(%, #{name}, %) [/if] ORDER BY u.id DESC [page:true]大概的约定是[query:接口名]声明这是一条查询 SQL接口名就是请求路径里用的名字。[#if 参数]和[/if]是动态条件判断等价于 MyBatis 里的if test。#{name}是参数占位符最终会作为 PreparedStatement 的参数传入可以防止 SQL 注入。[page:true]表示开启分页框架会自动在 SQL 后面追加LIMIT ? OFFSET ?这也是 pg 版必须要适配的地方。pg 版本下如果 SQL 里用了 MySQL 的习惯写法会直接报语法错误。比如 MySQL 的LIMIT #{offset}, #{limit}、反引号包裹字段、IFNULL函数在 pg 里分别对应LIMIT #{limit} OFFSET #{offset}、双引号包裹字段、COALESCE函数。4.3 pg 版 SQL 写法的几个注意事项场景MySQL 写法PostgreSQL 写法分页LIMIT 0, 10LIMIT 10 OFFSET 0字段/表名转义useruser双引号空值处理IFNULL(col, 0)COALESCE(col, 0)字符串拼接CONCAT(%, #{name}, %)同上pg 也支持 CONCAT布尔值tinyint(1)boolean / smallint时间格式化DATE_FORMAT(now(), %Y-%m-%d)TO_CHAR(now(), YYYY-MM-DD)自增 ID 回填LAST_INSERT_ID()RETURNING id如果你原来的接口业务是从 MySQL 迁过来的建议把所有 SQL 先拿到 pgAdmin 里跑一遍确认语法没问题再放到 SQL 文件里。SqlRest 只是把它拼接好的 SQL 发给数据库SQL 本身有语法错误它帮不了你。5. 启动、验证与 IDEA 调优5.1 找到启动类并运行在 demo 模块下找到带SpringBootApplication注解的类类名一般叫Application或SqlRestDemoApplication。右键类名选择 Run。如果启动时提示没有 Main class说明 IDEA 没有正确识别检查一下启动类是否在 demo 模块的src/main/java下。Project Structure 里该模块有没有被标记为 Sources蓝色。启动后控制台重点看这几个输出Tomcat started on port(s): 8080 (http) with context path Started Application in X.XXX seconds看到这两句基本就成了。如果还有一层 SQL 文件加载的初始化日志说明映射文件已经被扫描到。我说基本是因为启动成功只代表应用起来了SQL 映射有没有对还不一定需要用实际请求来验证。5.2 用 curl 验证接口启动成功后打开一个新的终端跑一个请求curl http://localhost:8080/sql/userList?name%E5%BC%A0参数是 URL 编码后的 UTF-8 中文。返回的 JSON 大概是{ code: 0, message: success, data: { total: 1, list: [ { id: 1, name: 张三, age: 25, email: zhangsandemo.com, status: 1 } ] } }注意一个细节分页接口返回的data里会有total和list两个字段这和单条查询/非分页查询的结构不同。如果你对接前端这个结构要事先跟对方说清楚不然前端拿到数据会懵。5.3 IDEA 中的启动参数与 Debug 技巧在 IDEA 的 Run Configuration 里可以加 VM options比如-Dserver.port8081 -Dlogging.level.sqlrestdebugserver.port的意思是如果你不想用默认端口可以在不修改 yml 的情况下覆盖。logging.level.sqlrestdebug会把 SqlRest 内部打印的 SQL 日志打开排查参数绑定时很有用。想看 SQL 拼出来到底是什么样直接在 IDEA 控制台里搜 Preparing:或者项目自定义的 SQL 输出标识。如果发现 SQL 里参数变成了?这是正常的因为用了 PreparedStatement要进一步看参数值装一个 DBeaver或者打开 pg 的log_statement all不过这种姿势生产环境慎用日志量太大了。5.4 pg 版启动中的实际运行现象我本地跑起来后有几个肉眼可见的区别这里跟你交个底首次启动比 MySQL 版略慢因为 HikariCP 连接 pg 时要多做一次握手实际影响可以忽略。pg 的status字段如果定义成 smallint返回给 Jackson 序列化后是 number前端如果要布尔值要么 SQL 里直接CAST(status AS BOOLEAN)要么在应用层转换。这个不算 bug但很多人会跟前端预期对不上。如果 SQL 里写了LIMIT 10 OFFSET 0这种写死的分页记得去掉交给[page:true]处理。不然当参数变化时分页会错乱排查起来会让人崩溃。6. 常见问题与排查实录6.1 启动时报数据库连接失败这个错误几乎每个人都有过我列几个典型的报错关键字原因处理办法Connection refusedpg 服务没起/端口不对确认 5432 端口监听netstat -ano | grep 5432Password authentication failed密码错误或 pg_hba 配置确认 yml 密码检查 pg_hba.conf 的认证方式Database xxx does not exist库名不对psql -U postgres -l查看已有数据库Driver not found驱动依赖缺失确认 pom 里有org.postgresql:postgresql依赖The server time zone ...MySQL 遗留习惯pg 不需要写 timezone删掉即可遇到Connection refused时先别急着改配置用 psql 命令行连接一下本地库psql -h localhost -p 5432 -U postgres -d sqlrest_demo能连上说明数据库没问题问题出在 Java 这侧连不上先处理数据库服务或认证问题再去调 yml。这个排查顺序能省掉大量无头苍蝇一样的时间。6.2 SQL 文件加载失败、接口 404启动没报错但请求/sql/userList返回 404这个问题九成出在sql-file-path配置上。首先要明确这个路径是相对于 classpath 的。如果配置文件在src/main/resources/application.ymlSQL 文件放在src/main/resources/sqls/那sql-file-path就写sqls/。很多人喜欢把 SQL 文件放在项目根目录的某个文件夹然后配置./sqls/或者绝对路径1.6 版本不一定支持直接结果就是 404。检查方法很简单编译之后看 target/classes 目录下面有没有 sqls/user.sql 这种结构。没有的话说明资源没进 classpath要么是构建配置没包含**/*.sql要么目录位置放错了。6.3 依赖下载失败或 IDEA 卡住国内网络下 Maven 首次拉依赖是比较痛苦的。除了前面说的阿里云镜像还有一个办法如果你在别的地方跑过同一套项目直接把本地仓库复制过来避免重新下载。IDEA 导入后一直卡在 Indexing 或 Resolving Dependencies 的状态建议关闭 IDEA删除项目目录里的.idea文件夹和根目录的target。重新打开导入让 IDEA 用 Maven 模型重新构建索引。这两种方式基本能解决 90% 的卡死情况。注意一点不要一边开着 IDEA 一边手动删 target一定要先关闭软件再操作。6.4 pg 特有的小坑汇总最后把 pg 版特有的坑统一列一下做成速查表问题现象原因与解决返回 JSON 里多出反引号或转义字符前端拿到脏数据一般是 SQL 里用了 MySQL 反引号pg 下改为双引号或去掉时间字段相差 8 小时Java 时间对不上pg 的 timestamp 不带时区Jackson 序列化时指定时区GMT8分页总数不对框架自动 count 解析失败复杂 SQL 建议拆成查询 count 两条映射或检查[page:true]位置SQL 里::类型转换报错如#{id}::int占位符和类型转换的顺序问题改用CAST(#{id} AS INT)中文乱码接口返回中文字符异常IDEA 运行配置里加-Dfile.encodingUTF-8同时检查数据库字符集主键重复用nextval序列冲突建表时用SERIAL或IDENTITY别手动插入 id 后不重置序列7. 后续可以怎么扩展SqlRest 跑通只是第一步实际用到生产环境还有几个值得继续搞的方向。一是多数据源路由。如果你的项目既有 pg 又有其他库SqlRest 1.6 是否支持多数据源需要看版本老版本一般只有配置里的单个spring.datasource。需要多个数据源的话可以查查项目有没有dynamic-datasource的集成方案或者自己封装一层数据源路由。二是 SQL 文件的工程化管理。SQL 文件多了以后命名规范、目录分模块、参数注释、权限控制都是要考虑的。不要让团队随随便便往一个目录里丢 SQL接口名冲突会让你崩溃。建议从一开始就约定一个业务模块一个目录接口名跟业务名对齐SQL 文件头部写清用途和参数说明。三是监控和安全。SQL 接口直接暴露给前端是有风险的生产环境至少要加一层鉴权比如网关层校验 token、限制接口白名单。这个开源项目解决的是接口生成效率的问题不解决谁能访问的问题这个边界要拎清楚。我个人在实际操作中最深的体会是SqlRest 这种轮子用好了是效率神器用不好是隐患。它最让人舒服的一点是改 SQL 不用重新走一遍发版流程最让人担心的也是这一点因为接口太容易加了管理成本容易失控。如果你正在考虑要不要在团队里引入建议先拿它搞定两个真实需求再决定要不要铺开。如果这篇文章帮你把 SqlRest 1.6 在 IDEA 里跑起来了我建议你接下来去翻一下它的源码重点看 SQL 文件解析那一块——你会发现它的设计思路其实非常轻巧正因为轻巧才有生命力。
返回列表