jdbc-plus是一款基于JdbcTemplate增强工具包, 基于JdbcTemplate已实现分页、多租户等插件,可自定义扩展插件

🚀 jdbc-plus简介

🚀 jdbc-plus是一款基于JdbcTemplate增强工具包, 基于JdbcTemplate已实现分页、多租户等插件,可自定义扩展插件。项目地址: GitHub - deeround/jdbc-plus: JdbcTemplate增强工具包,基于JdbcTemplate已实现分页、多租户等插件,可自定义扩展插件

特性:

  • 使用简单,对代码入侵很小
  • 可自定义任意扩展插件
  • 多租户参考mybatis-plus内置多租户的实现原理,理论上与mybatis-plus多租户插件支持度一样
  • 分页插件参考PageHelper的实现原理,使用简单,对代码入侵较小,还可以注册不支持的数据库
  • 免费开源,可任意使用修改代码

快速开始

  1. 引入jdbc-plus-spring-boot-starter
<dependency>
    <groupId>com.github.deeround</groupId>
    <artifactId>jdbc-plus-spring-boot-starter</artifactId>
    <version>${version}</version>
</dependency>
  1. 注入需要使用的插件
@Configuration
public class JdbcPlusConfig {

    /**
     * PaginationInterceptor是内置的分页插件(分页插件一定要注入在TenantLineHandler之后,可以通过Order来控制顺序)
     */
    @Bean
    @Order(9)
    public IInterceptor paginationInterceptor() {
        return new PaginationInterceptor();
    }

    /**
     * TenantLineHandler是内置的多租户插件插件
     */
    @Bean
    @Order(1)
    public IInterceptor tenantLineInterceptor() {
        return new TenantLineInterceptor(new TenantLineHandler() {
            /**
             * 当前租户ID
             */
            @Override
            public Expression getTenantId() {
                String currentTenantId = "test_tenant_1";//可以从请求上下文中获取(cookie、session、header等)
                return new StringValue(currentTenantId);
            }

            /**
             * 租户字段名
             */
            @Override
            public String getTenantIdColumn() {
                return "tenant_id";
            }

            /**
             * 根据表名判断是否忽略拼接多租户条件
             */
            @Override
            public boolean ignoreTable(String tableName) {
                return TenantLineHandler.super.ignoreTable(tableName);
            }
        });
    }
}

多租户插件

  1. 注入多租户插件
    /**
     * TenantLineHandler是内置的多租户插件插件
     */
    @Bean
    @Order(1)
    public IInterceptor tenantLineInterceptor() {
        return new TenantLineInterceptor(new TenantLineHandler() {
            /**
             * 当前租户ID
             */
            @Override
            public Expression getTenantId() {
                String currentTenantId = "test_tenant_1";//可以从请求上下文中获取(cookie、session、header等)
                return new StringValue(currentTenantId);
            }

            /**
             * 租户字段名
             */
            @Override
            public String getTenantIdColumn() {
                return "tenant_id";
            }

            /**
             * 根据表名判断是否忽略拼接多租户条件
             */
            @Override
            public boolean ignoreTable(String tableName) {
                return TenantLineHandler.super.ignoreTable(tableName);
            }
        });
    }
  1. service层执行SQL时自动添加租户字段
    @Autowired
    JdbcTemplate jdbcTemplate;

    public void insert() {
        this.jdbcTemplate.update("insert into test_user(id,name) values('1','wangwu')");
        //最终执行SQL:insert into test_user(id,name,tenant_id) values('1','wangwu','test_tenant_1')
    }

    public void delete() {
        this.jdbcTemplate.update("delete from test_user");
        //最终执行SQL:delete from test_user where tenant_id='test_tenant_1'
    }

    public void update() {
        this.jdbcTemplate.update("update test_user set name='lisi' where id='1'");
        //最终执行SQL:update test_user set name='lisi' where id='1' and tenant_id='test_tenant_1'
    }

    public List<Map<String, Object>> query() {
        return this.jdbcTemplate.queryForList("select * from test_user");
        //最终执行SQL:select * from test_user where tenant_id='test_tenant_1'
    }

分页插件

  1. 注入分页插件
    /**
     * PaginationInterceptor是内置的分页插件(分页插件一定要注入在TenantLineHandler之后,可以通过Order来控制顺序)
     */
    @Bean
    @Order(9)
    public IInterceptor paginationInterceptor() {
        return new PaginationInterceptor();
    }
  1. service层执行SQL时自动对SQL进行分页查询
    @Autowired
    JdbcTemplate jdbcTemplate;

    public PageInfo<Map<String, Object>> page1() {
        PageHelper.startPage(1, 2);
        List<Map<String, Object>> list = this.jdbcTemplate.queryForList("select * from test_user");//最终执行SQL:select * from test_user LIMIT 0,2
        PageInfo<Map<String, Object>> page = new PageInfo<>(list);//PageInfo对象包含了分页信息(总行数等)
        return page;
    }

    public PageInfo<Map<String, Object>> page2() {
        PageHelper.startPage(2, 2);
        List<Map<String, Object>> list = this.jdbcTemplate.queryForList("select * from test_user");//最终执行SQL:select * from test_user LIMIT 2,2
        PageInfo<Map<String, Object>> page = new PageInfo<>(list);//PageInfo对象包含了分页信息(总行数等)
        return page;
    }
  1. 自定义分页

当插件不支持的数据库分页,可以通过PageHelper.registerDialectAlias(String alias, Class clazz)注册一个自己分页实现类即可,也可以覆盖已支持的数据库分页。

自定义插件

示例:写一个打印SQL语句、执行参数、以及执行SQL耗时的监控插件。

  1. 编写MyStatInterceptor插件
/**
 * SQL监控插件
 */
@Slf4j
public class MyStatInterceptor implements IInterceptor {
    /**
     * 自定义插件是否支持
     */
    @Override
    public boolean supportMethod(final MethodInvocationInfo methodInfo) {
        return IInterceptor.super.supportMethod(methodInfo);
    }

    /**
     * SQL执行前方法(主要用于对SQL进行修改)
     */
    @Override
    public void beforePrepare(final MethodInvocationInfo methodInfo, JdbcTemplate jdbcTemplate) {
        log.info("原始SQL:{}", methodInfo.getSql());
        log.info("入参:{}", Arrays.toString(methodInfo.getArgs()));
        log.info("执行SQL开始时间:{}", LocalDateTime.now());
        methodInfo.getUserAttributes().put("startTime", LocalDateTime.now());
    }

    /**
     * SQL执行完成后方法(主要用于对返回值修改)
     *
     * @param result 原始返回对象
     * @return 处理后的返回对象
     */
    @Override
    public Object beforeFinish(Object result, final MethodInvocationInfo methodInfo, JdbcTemplate jdbcTemplate) {
        log.info("执行SQL结束时间:{}", LocalDateTime.now());
        LocalDateTime startTime = (LocalDateTime) methodInfo.getUserAttributes().get("startTime");
        log.info("执行SQL耗时:{}毫秒", Duration.between(startTime, LocalDateTime.now()).toMillis());
        return result;
    }
}
  1. 注入自定义插件
    /**
     * 自定义插件注入,注入位置按实际情况
     */
    @Bean
    @Order(0)
    public IInterceptor myStatInterceptor() {
        return new MyStatInterceptor();
    }
  1. 查看效果(查看打印日志)
c.g.d.j.p.s.config.MyStatInterceptor     : 原始SQL:select * from test_user
c.g.d.j.p.s.config.MyStatInterceptor     : 入参:[select * from test_user]
c.g.d.j.p.s.config.MyStatInterceptor     : 执行SQL开始时间:2023-04-23T16:35:58.151
c.g.d.j.p.s.config.MyStatInterceptor     : 执行SQL结束时间:2023-04-23T16:35:58.655
c.g.d.j.p.s.config.MyStatInterceptor     : 执行SQL耗时:503毫秒

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
当然,我可以帮你写一个基于JdbcTemplate查询数据库的基础代码。以下是一个示例代码: ```java import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.datasource.DriverManagerDataSource; public class JdbcTemplateExample { public static void main(String[] args) { // 设置数据库连接信息 DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://localhost:3306/mydatabase"); dataSource.setUsername("username"); dataSource.setPassword("password"); // 创建JdbcTemplate对象 JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); // 编写SQL查询语句 String sql = "SELECT * FROM role WHERE age > ?"; // 执行查询并获取结果 List<Map<String, Object>> roles = jdbcTemplate.queryForList(sql, 30); // 遍历结果集 for (Map<String, Object> role : roles) { String roleName = (String) role.get("role_name"); int age = (int) role.get("age"); System.out.println("Role Name: " + roleName + ", Age: " + age); } } } ``` 在上面的示例代码中,我们首先设置数据库连接信息,包括驱动类名、URL、用户名和密码。然后我们创建了一个JdbcTemplate对象,并传入数据源。接下来,我们编写了一个查询语句,使用`?`作为占位符,并将具体的参数值传入`queryForList()`方法中执行查询。最后,我们遍历查询结果并输出每个角色的名称和年龄。 请确保根据你自己的数据库设置正确的驱动类名、URL、用户名和密码。希望这个示例能帮到你!如果你有其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

黑色的迷迭香

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值