Skip to content

Latest commit

 

History

History
377 lines (256 loc) · 12.5 KB

BEST_PRACTICE.chs.md

File metadata and controls

377 lines (256 loc) · 12.5 KB

rabbit-sql 最佳实践

语言:English | 简体中文

准备工作

开发工具:IDEA Ultimate 版本 2023.1 以上。

Java版本:8 以上。

安装插件

  • 通过IDEA插件商店进行安装:Preferences(Settings) > Plugins > Marketplace > Search and find "rabbit sql" > Install Plugin
  • 通过插件资源库手动下载安装:Preferences(Settings) > Plugins > ⚙️ > Install plugin from disk... > 选择插件安装包(不需要解压)。

项目初始化

创建maven项目。

使用spring boot starter

pom.xml

java 17+

<dependency>
    <groupId>com.github.chengyuxing</groupId>
    <artifactId>rabbit-sql-spring-boot-starter</artifactId>
    <version>4.0.1</version>
</dependency>

java 8

<dependency>
    <groupId>com.github.chengyuxing</groupId>
    <artifactId>rabbit-sql-spring-boot-starter</artifactId>
    <version>3.1.4</version>
</dependency>

使用 rabbit-sql 提供的 Spring Boot Starter,可以简化配置,快速集成项目。通过 application.ymlapplication.properties 来配置数据库连接。

示例配置

spring:
  datasource:
    url: jdbc:postgresql://127.0.0.1:5432/postgres
    username: chengyuxing
    password: 

创建XQL文件管理配置

  1. .../src/main/resources 目录下创建文件 xql-file-manager.yml ,通过插件快速生成:

  2. 创建xql文件,通过插件来创建xql文件并自动注册到 xql-file-manager.yml,降低手动配置的错误率:

项目结构

  • 建议将 .xql 文件统一放置在一个目录中,如 /resources/xqls/,并按照模块或功能分类,方便维护和管理。

  • 将每个 .xql 文件的名称与模块功能对应,例如 user.xqlorder.xql,以便于查找和维护。

目录结构

/src
  ├─ main/
  |    ├─ java/org/example/
  |    └─ resources/xqls/
  |           ├─ user.xql
  |           └─ order.xql

XQL文件编写最佳实践

SQL语句命名

  • .xql 文件中,使用清晰的 SQL 语句名称,有助于提高可读性和可维护性。

  • 使用注释标记 SQL 语句名称,并为此条SQL添加具体描述。

  • 通过插件来创建一条SQL模版:

/*[findAllUsers]*/
/*#Some description.#*/
SELECT * FROM users;

/*[queryUserById]*/
/*#Some description.#*/
SELECT * FROM users WHERE id = :id;

SQL语句参数使用的是命名参数 :id,将被预编译处理为 ? 号,可有效避免SQL注入的风险。

动态SQL

  • 动态 SQL 可以通过 #if#for 等标签实现条件查询和循环查询,确保代码的灵活性。

  • 在复杂查询中,推荐将公共的 SQL 片段拆分成可复用的 SQL 片段,避免重复代码。

  • 通过插件提供的 live template 来生成标签语句模版,输入 xql 关键字来获取建议:

示例

select * from users where
-- #if :id >= 100
  id = 99
-- #else
  id = :id
-- #fi

SQL语句与接口方法映射

  • 默认情况下,sql名与方法名一一对应,否则使用 @XQL 注解进行方法映射,确保 SQL 语句名称始终与方法有明确的对应。
  • 按照约定,方法名的前缀代表了sql的类型,例如:queryUsers(); ,框架内部判定为 select 将执行查询操作,或者使用注解 @XQL 来改变默认的的查询行为。
  • 当一个 SQL 语句需要映射到多个方法时,使用 @XQL 注解指定 SQL 名称。

当 SQL 编写好以后,使用插件来快速生成接口文件方法注释文档,减少重复操作,提高效率:

Return Types: 选择需要返回的类型,有些 SQL 在一些情况是存在复用需要返回不同类型的需求。

T: 默认情况下,返回类型泛型内置了 DataRowMap,如果需要返回 java bean,则需要写完全限定类名,如上图 org.example.entity.User

可重复点击 Generate Code...,每次都会记录上一次的配置。

映射接口

  • @XQLMapper(...) 表明这是一个映射接口,并且指定具体的xql文件别名。

左侧导航图标表明sql和方法映射成功。

同一条 SQL 不同返回类型的复用,插件生成的接口格式为 SQL名+返回类型

每次重新点击 Generate Code... ,接口文件 //CODE-BEGIN ... //CODE-END 区域之间的内容不会被覆盖,例如:

// Rabbit-SQL plugin - Your methods  //CODE-BEGIN:methods
@Insert("users")
int addUser(User user);
// Rabbit-SQL plugin - End of your methods  //CODE-END:methods

接口映射的更多使用方法和注意事项可具体参考文档接口映射

接口使用指南

动态代理接口

在springboot启动类上添加注解 @XQLMapperScan ,所有被标记了 @XQLMapper 的接口都会被扫描到spring上下文中,即可通过依赖注入注入接口。

@SpringBootApplication
@XQLMapperScan
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }
}

ExampleService.java

@Autowired
private ExampleMapper exampleMapper;

Baki核心接口

除了接口映射之外,默认还提供了可选择的核心接口Baki

  • 通过 Baki 接口来执行增删改查、事务操作等基本数据库操作,避免直接与 JDBC 交互。
  • 每个 SQL 操作都通过传递 SQL 名称来执行,并传入参数映射。
  • 单表CRUD推荐使用基本的JPA的实体来进行操作。

SQL名示例

@Autowired
private Baki baki;

public Stream<DataRow> getUsersByName() {
    return baki.query("&example.queryAllUsers").args().stream();
}

JPA示例

baki.query(Guest.class)
    .where(g -> g.gt(Guest::getId, 5))
    .where(g -> g.lt(Guest::getId, 10))
    .where(g -> g.or(o -> o.in(Guest::getId, Arrays.asList(17, 18, 19))))
    .toList()

更详细的使用方法可参考文档

事务处理

  • 推荐在复杂的业务操作中使用 Baki 提供的事务支持,确保数据一致性。
  • 可以通过注解或手动方式进行事务管理。

示例

// 通过 Spring 注解管理事务
@Transactional
public void a() {
    
}
// 通过手动管理事务
// com.github.chengyuxing.sql.spring.autoconfigure.Tx
@Autowired;
Tx tx;

public void b(){
   tx.using(()->{

   });
}

性能优化

惰性查询

如果对查询结果需要进行二次处理转换等操作,推荐返回类型为 Stream,减少循环的次数,提升性能。

批量操作

对于批量插入、更新等操作,推荐使用批量提交,减少数据库的网络交互次数,提升性能。

baki.insert(Collection<Entity> data);
baki.of("&<sql名>").executeBatch(...);

insert, update, delete 通过传入集合来执行批量操作,或者通过 executeBatch 来执行批量操作。

缓存重复查询

针对频繁执行的相同查询,推荐使用应用层缓存或数据库查询缓存,减少重复 SQL 请求,提升系统响应速度。

实现接口:com.github.chengyuxing.sql.plugins.QueryCacheManager 来实现自定义的缓存层,并注册到 BakiDao#setQueryCacheManager 来启用缓存。

SQL优化
  • .xql 文件中,尽量使用索引字段进行查询,避免全表扫描。
  • 定期检查数据库的执行计划,优化慢查询。

错误处理与调试

错误日志
  • 确保所有 SQL 执行都被记录到日志中,尤其是异常发生时,方便排查问题。
  • 使用 rabbit-sql 插件进行动态SQL测试和调试,及时发现潜在问题。
常见错误处理
  • SQL 语法错误:在 .xql 文件中书写 SQL 时,确保 SQL 语法正确,尤其是在使用动态 SQL时。

  • 参数映射问题:使用 :参数名 时,确保传递的参数名与 SQL 中的占位符匹配,避免 SQL 语句的参数未正确绑定。

  • 连接释放问题:使用 Stream 作为返回类型时,需要在使用完毕后进行释放,一般使用 try-with-resource 来进行释放连接:

    try(Stream<DataRow> s = ...){
      s.map(...).
    }

插件使用指南

插件功能几乎都可以直接通过 IDEA 工具栏 XQL File Manager 面板来进行操作。

  • 使用 rabbit-sql-plugin 提供的 SQL 名自动完成、SQL 引用跳转和动态 SQL 测试功能,提升开发效率。
  • 通过插件导航直接跳转到对应的 SQL 语句,方便开发和调试。
  • 通过 New 来创建 xql-file-manager.yml ,XQL文件,SQL模版。

测试动态SQL

有效利用插件进行动态SQL测试,确保在项目启动前最大化降低错误率,尤其是针对复杂动态SQL的计算,提前明白每个参数对动态SQL计算结果的影响。

  • 选择第 2 步配置数据源的情况下可查看具体的执行效果,或者查看动态SQL的计算结果。

  • 通过 Execute '...' 来测试动态SQL。

  • 测试完毕点击第 4 步来回滚事务,以避免执行非查询语句造成数据被修改的问题。

安全性最佳实践

防止SQL注入

  • 使用参数化查询,确保所有的参数都通过 :参数名 占位符进行传递,避免 SQL 注入漏洞。
  • 禁止在 SQL 中直接拼接用户输入,所有用户输入都应该通过参数占位符传递。

数据库连接池配置

  • 配置合理的数据库连接池,避免数据库连接过多或连接泄漏,影响系统的可用性。

  • 使用 Spring Boot 的连接池配置,设置合理的最小和最大连接数。

    spring:
      datasource:
        hikari:
          minimum-idle: 5
          maximum-pool-size: 20
          connection-timeout: 30000
          idle-timeout: 600000
          max-lifetime: 1800000

版本控制与部署

  • 定期更新依赖:确保 rabbit-sql 的依赖库和插件保持最新版本,定期检查是否有安全漏洞或功能增强。
  • 自动化测试:对使用 rabbit-sql 的业务逻辑编写单元测试和集成测试,确保数据库操作的正确性和系统稳定性。

结语

rabbit-sql 是一个强大而灵活的持久层框架,通过遵循以上最佳实践,可以确保您的项目具有高效、可维护、性能优越的数据库交互逻辑。随时保持对最新功能和优化的关注,并根据项目需求灵活应用这些实践。

参考