个人开源项目,基于 JdbcTemplate 的持久层框架 -- SJdbc

github:https://github.com/Keguans/SJdbc

个人练手项目,欢迎大家给出意见

23.03.29更新 --版本1.1.10, 防止 sql 注入

23.03.27更新 -- 版本1.1,增加了缓存层。详情请移步:https://blog.csdn.net/qq_43159427/article/details/129777575

问:这是什么?

答:一个简单的基于 JdbcTemplate 的封装。

问:这玩意有什么用呢?

答:可以让你更方便的使用 JdbcTemplate。

问:那这破玩意怎么用?

答:(面部肌肉微微颤抖)好问题!

首先把依赖下载一下,链接:https://pan.baidu.com/s/1XnFBA4-5Is15T6g_dXLlOg?pwd=1234

导入到你的项目中,同时需要导入 JdbcTemplate 与 hutool 的依赖。

你需要配置一下 JdbcTemplate

import com.SJdbc.util.JdbcUtil;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;

import javax.sql.DataSource;

@Configuration
public class JdbcConfig {

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.hikari")
    public DataSource dataSource() {
        return new HikariDataSource();
    }

    @Bean
    public JdbcTemplate jdbcTemplate(DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }
}

然后创建你的实体类

import com.SJdbc.annotation.*;
import com.SJdbc.enums.IdTypeEnum;
import com.fasterxml.jackson.annotation.JsonFormat;

/**
 * Table 注解用于标注数据库表,里面的 name 是表名
 */
@Table(name = "t_user")
public class UserEntity {

    // 省略构造方法与 get set 方法

    /**
     * 主键
     * 主键用注解 Key 标注,默认逐渐字段名是“id”
     * type 为逐渐类型,自增与自动生成
     */
    @Key(type = IdTypeEnum.ID_AUTO)
    private Long id;

    /**
     * 用户名
     * 字段用注解 Column 标注,filed 是字段名
     * 如果数据库字段名与实体类的字段名一致,可不加 Column 注解
     */
    @Column(filed = "username")
    private String username;

    /**
     * 电话号码
     */
    private String phone;

    /**
     * 邮箱地址
     */
    private String email;

    /**
     * 密码
     */
    private String password;

    /**
     * 盐值
     */
    private String salt;

    /**
     * 创建时间
     * 注解 CreateTime 可在 jdbcUtil 中的 插入方法自动为该字段生成当前时间
     */
    @CreateTime
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date createTime;

    /**
     * 更新时间
     * 注解 UpdateTime 可在 JdbcUtil 中的 更新方法自动为该字段生成当前时间
     */
    @UpdateTime
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date updateTime;
}

之后就可以使用了。SJdbc 有两种用法,一种是使用 QueryModel 来进行sql 拼装(只支持SELECT, UPDATE, DELETE),与 JdbcUtil 配合使用

import com.SJdbc.enums.SqlCharacterEnum;
import com.SJdbc.model.Paging;
import com.SJdbc.model.QueryModel;
import com.SJdbc.util.JdbcUtil;
import com.test.entity.UserEntity;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.Date;
import java.util.List;

@Service
public class UserService {

    private final JdbcUtil jdbcUtil;

    public UserService(
            JdbcUtil jdbcUtil
    ) {
        this.jdbcUtil = jdbcUtil;
    }

    /**
     * 只使用 jdbcUtil
     */
    public void jdbcUtil() {
        // 主键查询
        UserEntity userEntity = jdbcUtil.getById(1L, UserEntity.class);
        // 增加,可获取主键值
        UserEntity add = new UserEntity();
        add.setUsername("user");
        jdbcUtil.insert(add);
        jdbcUtil.insertBatch(Collections.singletonList(add));
        // 更新(按照主键更新)
        userEntity.setEmail("xxx@gamil.com");
        jdbcUtil.update(userEntity);
        // 删除(按照主键删除)
        jdbcUtil.delete(1L, UserEntity.class);
    }

    /**
     * 使用 QueryModel
     */
    public void select() {
        // sql 拼装
        QueryModel queryModel = new QueryModel(UserEntity.class);
        queryModel.select().table().from().where().eq(UserEntity::getId, 1L);
        // 查询一个,sql 等同于 SELECT * FROM t_user WHERE id = 1
        UserEntity one = jdbcUtil.getOne(queryModel, UserEntity.class);
        System.out.println(one);

        // 分页查询,sql 等同于 SELECT username FROM t_user WHERE username like "%user%" and createTime >= now()
        queryModel.clearSql();
        queryModel.select()
                .table("username")
                .from()
                .where()
                .like(UserEntity::getUsername, "user")
                .and()
                .ge(UserEntity::getCreateTime, new Date());
        Paging<UserEntity> paging = jdbcUtil.paging(queryModel, new Paging.Page(1, 10), UserEntity.class);
        System.out.println(paging);

        // 查询列表,sql 等同于 SELECT * FROM t_user WHERE id = 1 OR (username = "user" AND createTime >= now())
        queryModel.clearSql();
        queryModel.select()
                .table()
                .from()
                .where()
                .eq(UserEntity::getId, 1L).or()
                .character(SqlCharacterEnum.LEFT_BRACKETS)
                .eq(UserEntity::getUsername, "user")
                .and()
                .ge(UserEntity::getCreateTime, new Date())
                .character(SqlCharacterEnum.RIGHT_BRACKETS);
        List<UserEntity> list = jdbcUtil.getList(queryModel, UserEntity.class);
        System.out.println(list);

        // 更新
        queryModel.clearSql();
        queryModel.update()
                .tableName()
                .set(UserEntity::getUsername, "123")
                .where()
                .eq(UserEntity::getId, 1L);
        int update = jdbcUtil.getJdbcTemplate().update(queryModel.sql.toString());
        System.out.println(update);

        // 删除
        queryModel.clearSql();
        queryModel.delete().from().where().eq(UserEntity::getId, 1L);
        int delete = jdbcUtil.getJdbcTemplate().update(queryModel.sql.toString());
        System.out.println(delete);
    }
}

另一种使用方式类似于 JPA,在注解 JdbcMapperScan 中指定 mapper 包地址(此方式同样只支持 SELECT, UPDATE, DELETE),这种使用方式主要是考虑到需要连表查询的情况

import com.SJdbc.annotation.Sql;
import com.test.entity.UserEntity;

import java.util.List;

/**
 * 需要在注解 JdbcMapperScan 中指定该类所在的包地址。
 * 该地址下只能用来写 mapper 类
 * 示例:@JdbcMapperScan(basePackages = "com.xxx.mapper")
 * 不需要写实现类,实现类会动态生成,最终统一由 JdbcTemplate 执行 sql 语句
 * 在其他地方直接注入此类就可使用(无需在意 idea 红线提示的找不到 bean)
 */
public interface UserMapper {

    /**
     * 默认方式,sql 中的 ?1 指的就是第一个入参
     */
    @Sql(sql = "SELECT * FROM t_user WHERE username = ?1")
    List<UserEntity> getListByUsername(String username);

    /**
     * 另一种方式,可以传对象作为入参
     */
    @Sql(sql = "SELECT * FROM t_user WHERE username = param.username", useParam = true)
    List<UserEntity> getListByUsernameType2(@Param(name = "param") UserEntity userEntity);
}

问:QueryModel 支持联表查询吗?

答:臣妾做不到啊!(QueryModel 是考虑作为单表应用的。本身联表查询是不被推荐的,理由我能找出几十条。但如果不得不联表查询,那么使用第二中自定义 mapper 的查询方式吧)

问:当前支持几种数据库?

答:当前只支持 mysql。如果你想用在 oracle 上也可以,但 bug 会多到你哭。至于以后会不会支持 oracle,看我有没有精力吧。(大概率我不会写,而是放出扩展组件)

问:这怎么会提示找不到 bean 呢?

答:因为你写的 mapper 只定义了接口,实现类是动态生成的,idea若是没有插件支持,当然会提示这个信息。不耽误使用。

问:可以指定多个 mapper 包吗?

答:当然可以。

问:你这 Logo 也太丑了吧?

                                                                            =@@      ,@@@@`               
                       ,]@@@@@@@@\`                  ,]/@@@@@@@            @@^     ,@/  =@@`              
                    ]@@[         @@^            ,/@@@[`   ,@@/            @@`     /@/   =@/               
                   @@^           @/           /@@/`      /@@`            @@^     ,@@   /@^                
                  *@@@                      @@@/        @@@`            =@@      @@^ ,@/                  
                   ,@@@\                  =@@@`        /@@^            ,@@^     =@@`                      
                     \@@@`               /@@/         /@@@             =@@     ,@@/                       
                       @@@@`            =@@`         =@@@^            ,@@^     /@@`                       
                        ,@@@\           ,[           @@@@             @@@`    =@@^                        
               ]]]@@@@\`  =@@@`                     /@@@^      ,@@/[[@@@@     @@@` @@@@@@@@@`  ,@@@@@@@   
        ]@@@@@@/[[[[[[[[`  =@@@                    ,@@@@     /@@`    =@@^    =@@@      @@    ,@@@[  @@^   
   ,/@@[                    \@@                    =@@@    =@@/     ,@@@     @@@`      @/   /@`     @^    
 ,@/                        @@@                    @@@/    @@@*    ,@@@`    =@@/     *@/   ,@`      `     
 =@@@\]]]]`          *]]]]]@@[                 ,]]/@@@]]]]]@@@\*,]@/@@\]]@/ @@@\]]]@@@^    ,@]]]]]]]]/@`  
   ,[@@@@@@@@@@@@@@@@@@/[[              ]@@@@@@@@@@@@@@@@@[ \@@@/`  ,@@@[  *@@@@@@@/`       ,@@@@@@@@[    
                                    ]@@@[`       @@@                                                      
                                  /@/           /@/                                                       
                                 /@@           /@`                                                        
                                 @@@         /@`                                                          
                                 ,@@\`   ,]@@`                                                            
                                    [[@@/[`                                                               

答:……

问:你写这东西也太烂了吧?好意思发出来?

答:我承认,我确实是个菜鸡。这个本身是我练手的项目,并没有进行深度测试,可预见的 bug 会非常多。虽然我菜,但是我永不服输。正好我脸皮厚,若是有什么意见就大方的说出来吧,谢谢了!

-- 我是 Keguans,一名生于 99 年的菜鸡研发

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Keguans

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

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

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

打赏作者

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

抵扣说明:

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

余额充值