BeetlSQL,Java Dao工具 BeetlSQL

BeetlSQL,Java Dao工具 BeetlSQL

BSD
Java 查看源码»
跨平台
2015-08-26
闲大赋

BeetlSQL的目标是提供开发高效,维护高效,运行高效的数据库访问框架,在一个系统多个库的情况下,提供一致的编写代码方式。支持如下数据平台

  • 传统数据库:MySQL,MariaDB,Oralce,Postgres,DB2,SQL Server,H2,SQLite,Derby,神通,达梦,华为高斯,人大金仓,PolarDB等
  • 大数据:HBase,ClickHouse,Cassandar,Hive
  • 物联网时序数据库:Machbase,TD-Engine,IotDB
  • SQL查询引擎:Drill,Presto,Druid
  • 内存数据库:ignite,CouchBase

BeetlSQL 不仅仅是简单的类似MyBatis或者是Hibernate,或者是俩着的综合,BeetlSQL目的是对标甚至超越Spring Data,是实现数据访问统一的框架,无论是传统数据库,还是大数据,还是查询引擎或者时序库,内存数据库。

BeetlSQL3 性能测试

测试维度是ops/ms,每毫秒的调用次数

Benchmark                         Mode  Cnt     Score     Error   Units
JMHMain.beetlsqlComplexMapping   thrpt    5   212.378 ±  26.222  ops/ms
JMHMain.beetlsqlExecuteJdbc      thrpt    5   428.713 ±  66.192  ops/ms
JMHMain.beetlsqlExecuteTemplate  thrpt    5   374.943 ±  20.214  ops/ms
JMHMain.beetlsqlFile             thrpt    5   433.001 ±  65.448  ops/ms
JMHMain.beetlsqlInsert           thrpt    5   236.244 ± 112.102  ops/ms
JMHMain.beetlsqlLambdaQuery      thrpt    5   247.289 ±  19.310  ops/ms
JMHMain.beetlsqlOne2Many         thrpt    5   108.132 ±  10.934  ops/ms
JMHMain.beetlsqlPageQuery        thrpt    5   203.751 ±   9.395  ops/ms
JMHMain.beetlsqlSelectById       thrpt    5   393.437 ±  15.685  ops/ms
JMHMain.jdbcExecuteJdbc          thrpt    5  1083.310 ±  80.947  ops/ms
JMHMain.jdbcInsert               thrpt    5   308.341 ± 231.163  ops/ms
JMHMain.jdbcSelectById           thrpt    5  1019.370 ±  92.946  ops/ms
JMHMain.jpaExecuteJdbc           thrpt    5    94.600 ±  15.624  ops/ms
JMHMain.jpaExecuteTemplate       thrpt    5   133.017 ±  12.954  ops/ms
JMHMain.jpaInsert                thrpt    5    81.232 ±  26.971  ops/ms
JMHMain.jpaOne2Many              thrpt    5   101.506 ±  11.301  ops/ms
JMHMain.jpaPageQuery             thrpt    5   117.748 ±   4.512  ops/ms
JMHMain.jpaSelectById            thrpt    5   335.945 ±  27.186  ops/ms
JMHMain.mybatisComplexMapping    thrpt    5   102.402 ±  11.129  ops/ms
JMHMain.mybatisExecuteTemplate   thrpt    5   202.619 ±  16.978  ops/ms
JMHMain.mybatisFile              thrpt    5   151.151 ±   4.251  ops/ms
JMHMain.mybatisInsert            thrpt    5   141.469 ±  43.092  ops/ms
JMHMain.mybatisLambdaQuery       thrpt    5    15.558 ±   1.481  ops/ms
JMHMain.mybatisPageQuery         thrpt    5    63.705 ±   7.592  ops/ms
JMHMain.mybatisSelectById        thrpt    5   197.130 ±  19.461  ops/ms
JMHMain.weedExecuteJdbc          thrpt    5   416.941 ±  22.256  ops/ms
JMHMain.weedExecuteTemplate      thrpt    5   439.266 ±  57.130  ops/ms
JMHMain.weedFile                 thrpt    5   477.561 ±  37.926  ops/ms
JMHMain.weedInsert               thrpt    5   231.444 ±  92.598  ops/ms
JMHMain.weedLambdaQuery          thrpt    5   422.707 ±  64.716  ops/ms
JMHMain.weedPageQuery            thrpt    5   246.018 ±  18.724  ops/ms
JMHMain.weedSelectById           thrpt    5   380.348 ±  20.968  ops/ms

代码示例

例子1,内置方法,无需写SQL完成常用操作

UserEntity user  = sqlManager.unique(UserEntity.class,1);

user.setName("ok123");
sqlManager.updateById(user);

UserEntity newUser = new UserEntity();
newUser.setName("newUser");
newUser.setDepartmentId(1);
sqlManager.insert(newUser);

输出日志友好,可反向定位到调用的代码

┏━━━━━ Debug [user.selectUserAndDepartment] ━━━
┣ SQL:     select * from user where 1 = 1 and id=?
┣ 参数:     [1]
┣ 位置:     org.beetl.sql.test.QuickTest.main(QuickTest.java:47)
┣ 时间:     23ms
┣ 结果:     [1]
┗━━━━━ Debug [user.selectUserAndDepartment] ━━━

例子2 使用SQL

String sql = "select * from user where id=?";
Integer id  = 1;
SQLReady sqlReady = new SQLReady(sql,new Object[id]);
List<UserEntity> userEntities = sqlManager.execute(sqlReady,UserEntity.class);
//Map 也可以作为输入输出参数
List<Map> listMap =  sqlManager.execute(sqlReady,Map.class);

例子3 使用模板SQL

String sql = "select * from user where department_id=#{id} and name=#{name}";
UserEntity paras = new UserEntity();
paras.setDepartmentId(1);
paras.setName("lijz");
List<UserEntity> list = sqlManager.execute(sql,UserEntity.class,paras);

String sql = "select * from user where id in ( #{join(ids)} )";
List list = Arrays.asList(1,2,3,4,5); Map paras = new HashMap();
paras.put("ids", list);
List<UserEntity> users = sqlManager.execute(sql, UserEntity.class, paras);

例子4 使用Query类

支持重构

LambdaQuery<UserEntity> query = sqlManager.lambdaQuery(UserEntity.class);
List<UserEntity> entities = query.andEq(UserEntity::getDepartmentId,1)
                    .andIsNotNull(UserEntity::getName).select();

例子5 把数十行SQL放到sql文件里维护

//访问user.md#select
SqlId id = SqlId.of("user","select");
Map map = new HashMap();
map.put("name","n");
List<UserEntity> list = sqlManager.select(id,UserEntity.class,map);

例子6 复杂映射支持

支持像mybatis那样复杂的映射

  • 自动映射
@Data
@ResultProvider(AutoJsonMapper.class)
 public static class MyUserView {
        Integer id;
        String name;
        DepartmentEntity dept;
 }

  • 配置映射,比MyBatis更容易理解,报错信息更详细
{
	"id": "id",
	"name": "name",
	"dept": {
		"id": "dept_id",
		"name": "dept_name"
	},
	"roles": {
		"id": "r_id",
		"name": "r_name"
	}
}

例子7 最好使用mapper来作为数据库访问类

@SqlResource("user") /*sql文件在user.md里*/
public interface UserMapper extends BaseMapper<UserEntity> {

    @Sql("select * from user where id = ?")
    UserEntity queryUserById(Integer id);

    @Sql("update user set name=? where id = ?")
    @Update
    int updateName(String name,Integer id);

    @Template("select * from user where id = #{id}")
    UserEntity getUserById(Integer id);

    @SpringData/*Spring Data风格*/
    List<UserEntity> queryByNameOrderById(String name);

    /**
     * 可以定义一个default接口
     * @return
     */
     default  List<DepartmentEntity> findAllDepartment(){
        Map paras = new HashMap();
        paras.put("exlcudeId",1);
        List<DepartmentEntity> list = getSQLManager().execute("select * from department where id != #{exlcudeId}",DepartmentEntity.class,paras);
        return list;
    }


    /**
     * 调用sql文件user.md#select,方法名即markdown片段名字
     * @param name
     * @return
     */
     List<UserEntity> select(String name);


    /**
     * 翻页查询,调用user.md#pageQuery
     * @param deptId
     * @param pageRequest
     * @return
     */
    PageResult<UserEntity>  pageQuery(Integer deptId, PageRequest pageRequest);
	
    @SqlProvider(provider= S01MapperSelectSample.SelectUserProvider.class)
    List<UserEntity> queryUserByCondition(String name);

    @SqlTemplateProvider(provider= S01MapperSelectSample.SelectUs
    List<UserEntity> queryUserByTemplateCondition(String name);

    @Matcher /*自己定义个Matcher注解也很容易*/
    List<UserEntity> query(Condition condition,String name);
}

你看到的这些用在Mapper上注解都是可以自定义,自己扩展的

例子8 使用Fetch 注解

可以在查询后根据Fetch注解再次获取相关对象,实际上@FetchOne和 @FetchMany是自定义的,用户可自行扩展

    @Data
    @Table(name="user")
    @Fetch
    public static class UserData {
        @Auto
        private Integer id;
        private String name;
        private Integer departmentId;
        @FetchOne("departmentId")
        private DepartmentData dept;
    }

    /**
     * 部门数据使用"b" sqlmanager
     */
    @Data
    @Table(name="department")
    @Fetch
    public static class DepartmentData {
        @Auto
        private Integer id;
        private String name;
        @FetchMany("departmentId")
        private List<UserData> users;
    }

例子9 不同数据库切换

可以自行扩展ConditionalSQLManager的decide方法,来决定使用哪个SQLManager

        SQLManager a = SampleHelper.init();
        SQLManager b = SampleHelper.init();
        Map<String, SQLManager> map = new HashMap<>();
        map.put("a", a);
        map.put("b", b);
        SQLManager sqlManager = new ConditionalSQLManager(a, map);

        //不同对象,用不同sqlManager操作,存入不同的数据库
        UserData user = new UserData();
        user.setName("hello");
        user.setDepartmentId(2);
        sqlManager.insert(user);

        DepartmentData dept = new DepartmentData();
        dept.setName("dept");
        sqlManager.insert(dept);

使用注解 @TargetSQLManager来决定使用哪个SQLManger

    @Data
    @Table(name = "department")
    @TargetSQLManager("b")
    public static class DepartmentData {
        @Auto
        private Integer id;
        private String name;
    }

例子10 如果想给每个sql语句增加一个sqlId标识

这样好处是方便数据库DBA与程序员沟通

 public static class SqlIdAppendInterceptor implements  Interceptor{
        @Override
        public void before(InterceptorContext ctx) {
            ExecuteContext context = ctx.getExecuteContext();
            String jdbcSql = context.sqlResult.jdbcSql;
            String info  = context.sqlId.toString();
            //为发送到数据库的sql增加一个注释说明,方便数据库dba能与开发人员沟通
            jdbcSql = "/*"+info+"*/\n"+jdbcSql;
            context.sqlResult.jdbcSql = jdbcSql;
        }
 }

例子11 代码生成框架

可以使用内置的代码生成框架生成代码何文档,也可以自定义的,用户可自行扩展SourceBuilder类

	List<SourceBuilder> sourceBuilder = new ArrayList<>();
	SourceBuilder entityBuilder = new EntitySourceBuilder();
	SourceBuilder mapperBuilder = new MapperSourceBuilder();
	SourceBuilder mdBuilder = new MDSourceBuilder();
	//数据库markdown文档
	SourceBuilder docBuilder = new MDDocBuilder();

	sourceBuilder.add(entityBuilder);
	sourceBuilder.add(mapperBuilder);
	sourceBuilder.add(mdBuilder);
	sourceBuilder.add(docBuilder);
    SourceConfig config = new SourceConfig(sqlManager,sourceBuilder);
   //只输出到控制台
	ConsoleOnlyProject project = new ConsoleOnlyProject();
	String tableName = "USER";
	config.gen(tableName,project);

例子13 定义一个Beetl函数

        GroupTemplate groupTemplate = groupTemplate();
        groupTemplate.registerFunction("nextDay",new NextDayFunction());

        Map map = new HashMap();
        map.put("date",new Date());
        String sql = "select * from user where create_time is not null and create_time<#{nextDay(date)}";
        List<UserEntity> count = sqlManager.execute(sql,UserEntity.class,map);

nextDay函数是一个Beetl函数,非常容易定义,非常容易在sql模板语句里使用

   public static class NextDayFunction implements Function {

        @Override
        public Object call(Object[] paras, Context ctx) {
            Date date = (Date) paras[0];
            Calendar c = Calendar.getInstance();
            c.setTime(date);
            c.add(Calendar.DAY_OF_YEAR, 1); // 今天+1天
            return c.getTime();
        }
    }

例子14 更多可扩展的例子

根据ID或者上下文自动分表,toTable是定义的一个Beetl函数,

    static final String USER_TABLE="${toTable('user',id)}";
    @Data
    @Table(name = USER_TABLE)
    public static class MyUser {
        @AssignID
        private Integer id;
        private String name;
    }

定义一个Jackson注解,@Builder是注解的注解,表示用Builder指示的类来解释执行,可以看到BeetlSQL的注解可扩展性就是来源于@Build注解

@Retention(RetentionPolicy.RUNTIME)
@Target(value = {ElementType.METHOD, ElementType.FIELD})
@Builder(JacksonConvert.class)
public @interface Jackson {

}

定义一个@Tenant 放在POJO上,BeetlSQL执行时候会给SQL添加额外参数,这里同样使用了@Build注解


/**
 * 组合注解,给相关操作添加额外的租户信息,从而实现根据租户分表或者分库
 */
@Retention(RetentionPolicy.RUNTIM@
@Target(value = {ElementType.TYPE})
@Builder(TenantContext.class)
public @interface Tenant {

}

使用XML而不是JSON作为映射

@Retention(RetentionPolicy.RUNTIME)
@Target(value = {ElementType.TYPE})
@Builder(ProviderConfig.class)
public @interface XmlMapping {
    String path() default "";
}

参考源码例子 PluginAnnotationSample了解如何定义自定的注解,实际上BeetlSQL有一半的注解都是通过核心注解扩展出来的

BeetlSQL的架构

除了SQLManager和ClassAnnoations,任何一部分都可以扩展

加载中

评论(27)

闲大赋
闲大赋 软件作者
看官网文档
言身寸言身寸
言身寸言身寸
大哥,给个mysql连接例子吧,配了好几天了,启动还是有报错 用了你好几年的Beelsql2的,这个3真是服了
局座
局座
zan
chenlei65368
chenlei65368
开源社区0424
开源社区0424
跨库怎么实现的
_
_casonol
请问下 beetl sql 有内置拦截器吗? 能实现 sql拦截,以做到数据结果过滤吗 ?
bako
bako
sql写注解里很烦。
哎呦-又忘了
哎呦-又忘了
我就想知道,一对多对象映射支持否
w
wolf_haung
思路跟我的一样,只是不知道BUG多不多。
选择与努力
选择与努力
遇到一个问题,mysql 和Spring boot 整合beetl 长时间不访问项目,会出现连接不上数据库,提示 无法回滚事务, 不知道怎么回事,请大神们指导下

BeetlSQL 3.1.0 发布,Spring Saga 事务支持

本次发布增强了Saga在spring下的支持,使用kafka提供重试以及重试失败后放入丢弃队列里 Saga是用来在微服务中的长事务管理,具备ACID中的ACD,不具备I,隔离性。在一定业务条件下,可以使用S...

11/17 13:35

BeetlSQL 3.0.10 发布,内置 sega 事务支持

本次发布主要增加了分布式Sega事务支持,适合多数据源 按照社区建议,修改了了springboot 的 yml配置方式 修改了@Jackson和@UpdateTime,本来是用来作为例子,但社区开发者提供了较好的完整实...

11/12 10:43

BeetlSQL 3.0.9 发布,Idea 插件发布

本次发布修复了bug以及发布了可在idea社区和专业版使用的BeetlSQL插件 修复代码生成到本地路径错误的Bug 修复FetchOne 抓取数据错误。 Idea插件发布 <dependency> <groupId>com.ibeetl<...

11/05 10:12

BeetlSQL 3.0.7 发布,新增 LambdaSubQuery

新增LambdaSubQuery,来源于 https://gitee.com/xiandafu/beetlsql/issues/I1WRHZ 修复代码生成POJO类的错误 <dependency> <groupId>com.ibeetl</groupId> <artifactId>beetlsql</art...

10/27 10:35

BeetlSQL 3.0.6 发布,Java 数据库访问框架

本次发布修复了少量Bug 修复SQLReady翻页bug修复 upsertByTemplate应该返回false而不是int的bug <dependency> <groupId>com.ibeetl</groupId> <artifactId>beetlsql</artifactId> ...

10/23 10:28

BeetlSQL 3.0.3 发布,JFinal 集成支持

本次发布集成了 JFinal4 修复升级到 3 后 TimeStatInterceptor 不兼容问题 修复升级到 3 后 SimpleCacheInterceptor 不兼容问题 集成了 JFinal4 <dependency> <groupId>com.ibeetl</gro...

10/19 10:08

BeetlSQL 3.0.1 发布,增强 Fetch 功能

本次发布增强了Fetch功能并修复了兼容2.x版本的PageQuery的错误 修复兼容2版本的PageQuery对象 Fetch框架增强,可以自定义Fetch实现,如新增@FetchSql @FetchSql注解,用于加载额外对象,比@...

10/11 11:09

BeetlSQL 3.0.0 正式发布,历经一年开发重构

牺牲了一年工作外业余时间的的构思和开发,BeetlSQL终于迎来了新的开始,BeetlSQL3正式发布。BeetlSQL3不仅仅类似MyBatis和JPA的综合,更大的目标是作为数据系统访问框架而非工具。对标Sprin...

10/07 15:30

BeetlSQL 3.0.0-M6 发布

本次发布,继续集成和支持国内数据库,添加更多单元测试。BeetlSQL3正式版即将发布 阿里云数据库PolarDB 支持 单元测试通过,覆盖100+API 所有例子从mysql更改为H2 修复了若干3.0的bug,此版...

09/24 14:32

BeetlSQL 2.13.5.RELEASE 发布

* 修订了支持JDK的LocalDate和LocalDateTime的bug * BeetlSQL 使用新的Beetl3.2 <dependency> <groupId>com.ibeetl</groupId> <artifactId>beetlsql</artifactId> <version>2.13....

09/24 10:45

没有更多内容

加载失败,请刷新页面

2
回答
beetlSQL新增数据的时候获取主键的方式

public int save(Member member) { UUIDGenerate.UUID(sqlManager); KeyHo...

2017/02/27 16:52
1
回答
在.md里写的自定义的insert语句,如何返回主键

@闲大赋 您好,想跟您请教个问题: 比如一个名叫 goods 的表 只有 id(主键) 和 goods_name 俩个字段,当我在.md文件里写了一句新增...

2019/11/08 11:25
2
回答
beetlSQL的内置updateById更新数据的时候 set值默认不进行非空判断吗
闲大赋 的回答 2017/02/17 10:56
最佳答案
使用 updateTemplateById 来忽略空值
1
回答
beetlsql

@闲大赋 你好,想跟你请教个问题:beetl有没有直接处理存储过程结果集的方法

2018/12/19 10:29
119
回答
高手问答第 178 期 —— Beetl 作者带来的分布式架构分享
博文视点 的回答 2017/11/30 16:42
最佳答案
高手问答第 178 期 —— 高手问答第 178 期 —— Beetl 作者带来的分布式架构分享 @Flylinran @德古拉-大猫 @赤脚小子 @Rober萝卜 @ChrisYuan 恭喜以上五位网友或获得《Spring Boot 2精髓:从构建小系统到架构分布式大系统》图书一本 请私信 ...
8
回答
BeetlSQL 单字段保存异常
闲大赋 的回答 2017/02/15 09:33
最佳答案
明白了,那这是个bug,你的贴图已经清楚的显示出来了, insert into xxxx () values () 列表为空 会出错 我改改吧,下个版本发布吧,可能就这俩天
11
回答
beetlsql SQL 模板参数日期格式化无效
闲大赋 的回答 2017/02/10 15:01
最佳答案
现在临时解决方法,你别用格式化函数,因为还不支持,你可以写个方法,或者用现成的方法,比如 ${strutil.formatDate(user.orderTime,’yyyy-MM-dd’)}
2
回答
Spring boot 集成 beetlsql运行警告,但不影响使用

系统按照 http://git.oschina.net/xiandafu/springboot_beetl_beetlsql 示例搭建。 代码如下: /*...

2017/01/19 17:11
1
回答
user.findById接口参数如下位置{0=没有申明params的参数}定义错误,无法映射

public interface UserDao extends BaseMapper<User>{ User findById(String ...

2016/12/16 15:44

没有更多内容

加载失败,请刷新页面

打算重写BeetlSQL

新年做开源欲望不强烈了,主要原因 事业一塌糊涂,想好好干工作(尽管在帝都有车有房,当比起哪些专注事业的人来说,还是差很多) 养家糊口很重要,累计开源几年下来得利不超过8000元,还不如...

01/03 15:03
735
2
BeetlSQL 3.0 进展

目前搞了20%了,主要完成了SQL执行前的一些准备操作,加油吧,搞了2个月才20%,希望后面进展快点 关于3.0的新特性,在 https://gitee.com/xiandafu/beetlsql/blob/3.0/3.0.md . 3.0最主要的俩...

03/26 12:53
281
0
Beetlsql扩展之自定义Mapper

BeetlSql 有一个BaseMapper,提供了很多内置的Dao操作,如增删改查等10几个方法,用户只需要些一个类继承此接口便能很快的完成一个Dao,比如 public interface UserDao extends BaseMapper<...

2017/09/26 21:59
1K
0
BeetlSQL 实现 ORMapping查询

我在 hibernate,mybatis,beetlsql 全面比较 中说明了BeetlSQL 在开发效率,维护性,跨数据库等各指标全面比hibernate 占优,但在ORM 方面不如Hibernate,这么多年来,hibernate已经成为Java的...

2016/08/21 20:44
5.7K
5
BeetlSQL 3 功能预览

BeetlSQL 3 目前正在研发过程,预计9月能发版。相比于BeetlSQL2,有非常多的改进,本博客会用一部分介绍BeetlSQL3的功能,另外一部分介绍如何定制Beetl3。 BeetSql是一个全功能DAO工具, 同时...

07/15 17:21
770
4
beetlsql 命名修复

import org.beetl.sql.core.UnderlinedNameConversion; import org.beetl.sql.core.kit.StringKit; /** * */ public class YJUnderlinedNameConversion extends UnderlinedNameConversion { ...

2019/03/18 21:26
25
0
ACT 与 Beetlsql 的搭配使用 一

扩展课程 第一章 ACT 与 Beetlsql 的搭配使用. 一. 什么是 BeetlSQL BeetlSQL 是国内知名开源作者闲大赋的最新力作. 主要的目标是代替 Mybatis . 相比 Mybatis 优势在于: MarkDown 维护复杂 ...

2019/07/10 16:04
288
2
ACT 与 Beetlsql 的搭配使用 二

第2章 ACT 与 Beetlsql 的搭配实战 上一节为了便利,我们使用 H2 做为示例数据库,本节我们将使用国内目前最多人使用的 MySQL,来实战一下. 在本节里我们一起学习: ACT里如何连接数据库及配置多...

2019/07/10 18:41
108
2
5分钟 BeetlSQL 快速入门

企业应用面临的问题 高效编写数据库访问代码 内置CRUD,不需要写SQL 支持OR/Mapping 悲观锁,乐观锁,逻辑删除等辅助支持等 即支持简单的CRUD,也支持数十行,上百行SQL编写 跨数据库平台支持...

2018/04/08 15:33
6.9K
2
BeetlSQL 3 功能预览2

本博客介绍了BeetlSQL3提供的高级扩展功能,以下问题可以在BeetlSQL3中轻易扩展实现 定义一个注解@Jackson能把属性对象转化成json存入到数据库 定义@LoadOne, 当数据加载完毕后,可以加载更多...

08/01 21:29
159
0

没有更多内容

加载失败,请刷新页面

返回顶部
顶部