AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified Apache-2.0 Self-run

Jooq Xugudb Adapter

skill-kourou25-xugudb-dev-skills-jooq-xugudb-adapter · by kourou25

jOOQ(Java Object Oriented Query)框架适配虚谷数据库(XuguDB)的完整指南。当用户需要将基于 jOOQ 的 Java 项目配置或适配到虚谷数据库时使用此技能,包括依赖配置、代码生成配置、数据库连接、查询构建、事务管理等。适用于从 MySQL/PostgreSQL 迁移或新建虚谷数据库项目。

— No reviews yet
0 installs
29 views
0.0% view→install

Install

$ agentstack add skill-kourou25-xugudb-dev-skills-jooq-xugudb-adapter

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • ✓ Prompt-injection patterns
  • ✓ Secret / credential exfiltration
  • ✓ Dangerous shell & filesystem operations
  • ✓ Untrusted network calls
  • ✓ Known-malicious package signatures

What it can access

  • ✓ Network access No
  • ✓ Filesystem access No
  • ✓ Shell / process execution No
  • ✓ Environment & secrets No
  • ✓ Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-kourou25-xugudb-dev-skills-jooq-xugudb-adapter)

Reliability & compatibility

✓ Security review passed
0 installs to date
— no reviews yet
● 3mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Jooq Xugudb Adapter? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

jOOQ 虚谷数据库适配指南

概述

本技能提供 jOOQ 框架适配虚谷数据库(XuguDB)的完整配置指南。jOOQ 是一个轻量级的 Java ORM 框架,通过代码生成的方式将数据库表映射为 Java 类,并提供类型安全的 SQL 构建 API。

适用场景:

  • 从 MySQL/PostgreSQL 迁移现有 jOOQ 项目到虚谷数据库
  • 新建基于 jOOQ 的虚谷数据库项目
  • 需要类型安全的 SQL 构建能力
  • 需要代码生成功能简化数据库操作

核心特性:

  • 类型安全的 SQL 构建 API
  • 自动代码生成,将数据库表映射为 Java 类
  • 支持复杂的多表关联查询
  • 与 Spring Boot 无缝集成
  • 支持事务管理和批量操作

快速开始

1. 添加依赖

Maven 配置:


    org.jooq
    jooq
    3.18.7

    com.xugudb
    xugu-jdbc
    12.3.4

    com.zaxxer
    HikariCP
    5.0.1

Gradle 配置:

implementation 'org.jooq:jooq:3.18.7'
implementation 'com.xugudb:xugu-jdbc:12.3.4'
implementation 'com.zaxxer:HikariCP:5.0.1'

2. 配置数据库连接

连接字符串格式:

jdbc:xugu://host:port/database?current_schema=schema&CHAR_SET=UTF8&COMPATIBLE_MODE=MYSQL

连接配置示例:

import org.jooq.DSLContext;
import org.jooq.impl.DSL;
import org.jooq.SQLDialect;
import java.sql.DriverManager;
import java.sql.Connection;

// 创建数据库连接
String url = "jdbc:xugu://127.0.0.1:5138/SYSTEM?current_schema=PUBLIC&CHAR_SET=UTF8&COMPATIBLE_MODE=MYSQL";
String username = "SYSDBA";
String password = "SYSDBA";

try (Connection connection = DriverManager.getConnection(url, username, password)) {
    // 创建 jOOQ DSLContext,使用 MYSQL 方言
    DSLContext dsl = DSL.using(connection, SQLDialect.MYSQL);
    
    // 使用 jOOQ 执行查询
    var result = dsl.select()
                    .from("users")
                    .fetch();
}

3. 配置代码生成

Maven 插件配置:


    
        
        
            org.jooq
            jooq-codegen-maven
            3.18.7
            
            
                
                    generate-jooq-sources
                    generate-sources
                    
                        generate
                    
                
            
            
            
                
                
                    com.xugu.cloudjdbc.Driver
                    jdbc:xugu://127.0.0.1:5138/SYSTEM?current_schema=PUBLIC&CHAR_SET=UTF8&COMPATIBLE_MODE=MYSQL
                    SYSDBA
                    SYSDBA
                
                
                
                
                    
                        
                        org.jooq.meta.mysql.MYSQLDatabase
                        
                        
                        PUBLIC
                        
                        
                        .*
                        
                        
                        flyway_schema_history|schema_version
                    
                    
                    
                        
                        true
                        
                        
                        true
                        
                        
                        true
                    
                    
                    
                        
                        com.example.jooq
                        
                        
                        src/main/java
                        
                        
                        true
                    
                
            
        
    

执行代码生成:

mvn clean generate-sources

核心功能

1. 基础 CRUD 操作

查询所有记录:

import static com.example.jooq.Tables.USERS;
import com.example.jooq.tables.records.UsersRecord;
import java.util.List;

public List findAll() {
    return dsl.selectFrom(USERS)
              .fetch();
}

条件查询:

public Optional findById(Long id) {
    return dsl.selectFrom(USERS)
              .where(USERS.ID.eq(id))
              .fetchOptional();
}

public List findByNameLike(String name) {
    return dsl.selectFrom(USERS)
              .where(USERS.NAME.like("%" + name + "%"))
              .fetch();
}

插入记录:

public UsersRecord insert(String name, String email) {
    return dsl.insertInto(USERS)
              .set(USERS.NAME, name)
              .set(USERS.EMAIL, email)
              .returning(USERS.ID, USERS.NAME, USERS.EMAIL)
              .fetchOne();
}

更新记录:

public int update(Long id, String name, String email) {
    return dsl.update(USERS)
              .set(USERS.NAME, name)
              .set(USERS.EMAIL, email)
              .where(USERS.ID.eq(id))
              .execute();
}

删除记录:

public int delete(Long id) {
    return dsl.deleteFrom(USERS)
              .where(USERS.ID.eq(id))
              .execute();
}

2. 多表关联查询

内连接查询:

import static com.example.jooq.Tables.USERS;
import static com.example.jooq.Tables.ORDERS;
import static com.example.jooq.Tables.PRODUCTS;

var result = dsl.select(
                    USERS.NAME,
                    ORDERS.ORDER_DATE,
                    PRODUCTS.NAME.as("product_name")
                )
                .from(USERS)
                .join(ORDERS).on(USERS.ID.eq(ORDERS.USER_ID))
                .join(PRODUCTS).on(ORDERS.PRODUCT_ID.eq(PRODUCTS.ID))
                .where(USERS.ACTIVE.eq(true))
                .fetch();

左连接查询:

var leftJoinResult = dsl.select(
                            USERS.NAME,
                            DSL.count(ORDERS.ID).as("order_count")
                        )
                        .from(USERS)
                        .leftOuterJoin(ORDERS).on(USERS.ID.eq(ORDERS.USER_ID))
                        .groupBy(USERS.NAME)
                        .fetch();

3. 聚合查询

var aggregation = dsl.select(
                        USERS.DEPT_ID,
                        DSL.count().as("user_count"),
                        DSL.avg(USERS.SALARY).as("avg_salary"),
                        DSL.max(USERS.SALARY).as("max_salary"),
                        DSL.min(USERS.SALARY).as("min_salary")
                    )
                    .from(USERS)
                    .groupBy(USERS.DEPT_ID)
                    .having(DSL.count().gt(5))
                    .orderBy(USERS.DEPT_ID)
                    .fetch();

4. 子查询

// 子查询示例
var subquery = dsl.select(ORDERS.USER_ID)
                  .from(ORDERS)
                  .where(ORDERS.STATUS.eq("COMPLETED"));

var result = dsl.selectFrom(USERS)
                .where(USERS.ID.in(subquery))
                .fetch();

5. 分页查询

public List findWithPagination(int page, int size) {
    return dsl.selectFrom(USERS)
              .orderBy(USERS.ID.asc())
              .limit(size)
              .offset((page - 1) * size)
              .fetch();
}

Spring Boot 集成

1. 配置文件

application.yml:

spring:
  datasource:
    url: jdbc:xugu://127.0.0.1:5138/SYSTEM?current_schema=PUBLIC&CHAR_SET=UTF8&COMPATIBLE_MODE=MYSQL
    username: SYSDBA
    password: SYSDBA
    driver-class-name: com.xugu.cloudjdbc.Driver
    
    # HikariCP 连接池配置
    hikari:
      maximum-pool-size: 20
      minimum-idle: 5
      idle-timeout: 300000
      connection-timeout: 20000

# jOOQ 配置
jooq:
  sql-dialect: MYSQL

2. 自动配置类

import org.jooq.DSLContext;
import org.jooq.impl.DSL;
import org.jooq.SQLDialect;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;

@Configuration
public class JooqConfiguration {
    
    @Bean
    public DSLContext dslContext(DataSource dataSource) {
        return DSL.using(dataSource, SQLDialect.MYSQL);
    }
}

3. Repository 示例

import org.jooq.DSLContext;
import org.springframework.stereotype.Repository;
import static com.example.jooq.Tables.USERS;
import com.example.jooq.tables.records.UsersRecord;
import java.util.List;
import java.util.Optional;

@Repository
public class UserRepository {
    
    private final DSLContext dsl;
    
    public UserRepository(DSLContext dsl) {
        this.dsl = dsl;
    }
    
    public List findAll() {
        return dsl.selectFrom(USERS)
                  .fetch();
    }
    
    public Optional findById(Long id) {
        return dsl.selectFrom(USERS)
                  .where(USERS.ID.eq(id))
                  .fetchOptional();
    }
    
    public UsersRecord insert(String name, String email) {
        return dsl.insertInto(USERS)
                  .set(USERS.NAME, name)
                  .set(USERS.EMAIL, email)
                  .returning(USERS.ID, USERS.NAME, USERS.EMAIL)
                  .fetchOne();
    }
    
    public int update(Long id, String name, String email) {
        return dsl.update(USERS)
                  .set(USERS.NAME, name)
                  .set(USERS.EMAIL, email)
                  .where(USERS.ID.eq(id))
                  .execute();
    }
    
    public int delete(Long id) {
        return dsl.deleteFrom(USERS)
                  .where(USERS.ID.eq(id))
                  .execute();
    }
}

事务管理

1. 编程式事务

import org.jooq.DSLContext;
import org.jooq.impl.DSL;

public class TransactionExample {
    
    private final DSLContext dsl;
    
    public TransactionExample(DSLContext dsl) {
        this.dsl = dsl;
    }
    
    public void executeInTransaction() {
        dsl.transaction(configuration -> {
            DSLContext txDsl = DSL.using(configuration);
            
            // 在事务中执行多个操作
            txDsl.insertInto(USERS)
                 .set(USERS.NAME, "张三")
                 .set(USERS.EMAIL, "zhangsan@example.com")
                 .execute();
            
            txDsl.update(USERS)
                 .set(USERS.ACTIVE, true)
                 .where(USERS.NAME.eq("张三"))
                 .execute();
        });
    }
    
    // 带返回值的事务
    public UsersRecord insertAndReturn() {
        return dsl.transactionResult(configuration -> {
            DSLContext txDsl = DSL.using(configuration);
            
            return txDsl.insertInto(USERS)
                        .set(USERS.NAME, "李四")
                        .set(USERS.EMAIL, "lisi@example.com")
                        .returning(USERS.ID, USERS.NAME, USERS.EMAIL)
                        .fetchOne();
        });
    }
}

2. Spring 声明式事务

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.jooq.DSLContext;

@Service
public class UserService {
    
    private final DSLContext dsl;
    
    public UserService(DSLContext dsl) {
        this.dsl = dsl;
    }
    
    @Transactional
    public void createUserWithOrders(UserDto userDto, List orders) {
        // 创建用户
        UsersRecord user = dsl.insertInto(USERS)
                              .set(USERS.NAME, userDto.getName())
                              .set(USERS.EMAIL, userDto.getEmail())
                              .returning(USERS.ID, USERS.NAME, USERS.EMAIL)
                              .fetchOne();
        
        // 创建订单
        for (OrderDto orderDto : orders) {
            dsl.insertInto(ORDERS)
               .set(ORDERS.USER_ID, user.getId())
               .set(ORDERS.PRODUCT_ID, orderDto.getProductId())
               .set(ORDERS.AMOUNT, orderDto.getAmount())
               .execute();
        }
    }
    
    @Transactional(readOnly = true)
    public List findAllUsers() {
        return dsl.selectFrom(USERS)
                  .fetch();
    }
}

批量操作

1. 批量插入

import org.jooq.impl.DSL;
import java.util.Arrays;
import java.util.List;

public void batchInsert(List users) {
    dsl.batch(
        dsl.insertInto(USERS, USERS.NAME, USERS.EMAIL)
           .values((String) null, (String) null)
    ).bind(users.stream()
                .map(u -> new Object[] { u.getName(), u.getEmail() })
                .toArray(Object[][]::new))
     .execute();
}

// 使用 loadInto 批量插入(适用于大量数据)
public void bulkInsert(List users) {
    dsl.loadInto(USERS)
       .onDuplicateKeyIgnore()
       .loadArrays(users.stream()
                        .map(u -> new Object[] { u.getName(), u.getEmail() })
                        .toArray(Object[][]::new))
       .fields(USERS.NAME, USERS.EMAIL)
       .execute();
}

2. 批量更新

public void batchUpdate(List users) {
    dsl.batch(
        dsl.update(USERS)
           .set(USERS.NAME, (String) null)
           .set(USERS.EMAIL, (String) null)
           .where(USERS.ID.eq((Long) null))
    ).bind(users.stream()
                .map(u -> new Object[] { u.getName(), u.getEmail(), u.getId() })
                .toArray(Object[][]::new))
     .execute();
}

性能优化

1. 索引优化

-- 为常用查询字段创建索引
CREATE INDEX idx_users_name ON users(name);
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_users_created_at ON users(created_at);

-- 复合索引
CREATE INDEX idx_users_dept_active ON users(dept_id, active);

2. 查询优化

// 使用 fetchLazy 进行流式处理(适用于大数据量)
public void processLargeData() {
    try (Cursor cursor = dsl.selectFrom(USERS)
                                         .fetchLazy()) {
        while (cursor.hasNext()) {
            UsersRecord record = cursor.fetchOne();
            // 处理每条记录
            processRecord(record);
        }
    }
}

// 使用 fetchSize 控制每次获取的记录数
public List fetchWithSize(int fetchSize) {
    return dsl.selectFrom(USERS)
              .fetchSize(fetchSize)
              .fetch();
}

3. 连接池优化

// HikariCP 连接池优化配置
HikariConfig config = new HikariConfig();
config.setMaximumPoolSize(20);           // 最大连接数
config.setMinimumIdle(5);               // 最小空闲连接数
config.setIdleTimeout(300000);          // 空闲超时时间(5分钟)
config.setConnectionTimeout(20000);     // 连接超时时间(20秒)
config.setMaxLifetime(1800000);         // 连接最大生命周期(30分钟)
config.setLeakDetectionThreshold(60000); // 泄漏检测阈值(1分钟)

测试配置

1. 单元测试

import org.jooq.DSLContext;
import org.jooq.impl.DSL;
import org.jooq.SQLDialect;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.sql.DriverManager;
import java.sql.Connection;

class UserRepositoryTest {
    
    private DSLContext dsl;
    private UserRepository repository;
    
    @BeforeEach
    void setUp() throws Exception {
        // 使用测试数据库连接
        String url = "jdbc:xugu://127.0.0.1:5138/SYSTEM?current_schema=PUBLIC&CHAR_SET=UTF8&COMPATIBLE_MODE=MYSQL";
        Connection connection = DriverManager.getConnection(url, "SYSDBA", "SYSDBA");
        dsl = DSL.using(connection, SQLDialect.MYSQL);
        repository = new UserRepository(dsl);
    }
    
    @Test
    void testFindAll() {
        var users = repository.findAll();
        assertNotNull(users);
    }
    
    @Test
    void testInsert() {
        var user = repository.insert("测试用户", "test@example.com");
        assertNotNull(user);
        assertEquals("测试用户", user.getName());
    }
}

2. 集成测试(Spring Boot)

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.transaction.annotation.Transactional;

@SpringBootTest
@ActiveProfiles("test")
@Transactional
class UserRepositoryIntegrationTest {
    
    @Autowired
    private UserRepository repository;
    
    @Test
    void testFindById() {
        var user = repository.findById(1L);
        assertTrue(user.isPresent());
    }
}

常见问题与解决方案

1. 方言不匹配

问题:jOOQ 生成的 SQL 语法与虚谷数据库不兼容。

解决方案:

  • 使用 SQLDialect.MYSQL 作为方言
  • 确保虚谷数据库连接字符串中包含 COMPATIBLE_MODE=MYSQL

2. 数据类型映射

问题:某些数据类型映射不正确。

解决方案:

  • 在代码生成配置中使用 forcedTypes 进行类型转换
  • 检查虚谷数据库的数据类型文档

3. 性能问题

问题:查询性能不佳。

解决方案:

  • 为常用查询字段创建索引
  • 使用连接池并优化连接池参数
  • 使用 fetchLazy 进行流式处理大数据量
  • 避免 N+1 查询问题

4. 事务问题

问题:事务不生效或行为异常。

解决方案:

  • 确保使用正确的事务管理方式(编程式或声明式)
  • 检查数据库连接的自动提交设置
  • 使用 Spring 的 @Transactional 注解管理事务

最佳实践

  1. 使用代码生成:充分利用 jOOQ 的代码生成器,获得类型安全的 SQL 构建能力
  2. 连接池管理:始终使用连接池管理数据库连接
  3. 事务管理:对于多步操作,使用事务确保数据一致性
  4. 性能优化:为常用查询创建索引,使用批量操作减少数据库往返
  5. 测试覆盖:编写单元测试和集成测试,确保代码质量
  6. 日志配置:在开发环境开启 SQL 日志,便于调试
  7. 版本管理:使用数据库迁移工具

…

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.