• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

BeetlSQL: 简洁方便,功能强大的ORM工具

原作者: [db:作者] 来自: 网络 收藏 邀请

开源软件名称:

BeetlSQL

开源软件地址:

https://gitee.com/xiandafu/beetlsql

开源软件介绍:

Maven Central

数据访问框架

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

  • 传统数据库:MySQL(国内兼容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,是实现数据访问统一的框架,无论是传统数据库,还是大数据,还是查询引擎或者时序库,内存数据库。

直接在线试用BeetlSQL http://121.42.237.11:8080/beetlsql_online/

  • 作者: 闲大赋,Gavin.King,Sue,Zhoupan,woate,darren,蚊子
  • 开发时间:2015-07
  • 网站 http://ibeetl.com
  • qq群 219324263(满) 252010126

BeetlSQL 3.x 使用说明,当前版本](https://www.kancloud.cn/xiandafu/beetlsql3_guide)

社区提供的文档 https://beetlsql-doc.vercel.app/

<dependency>    <groupId>com.ibeetl</groupId>    <artifactId>beetlsql</artifactId>    <version>3.${version}</version></dependency>

BeetlSQL 2.x 使用说明,旧版本

<dependency>    <groupId>com.ibeetl</groupId>    <artifactId>beetlsql</artifactId>    <version>2.13.3.RELEASE</version></dependency>

适合用户

  • 你不想把精力浪费在简单据库增删改查上?BeetlSQL 内置数据库的CRUD功能
  • 你是属于以SQL为中心的程序员派别。BeetlSQL提供了较好的SQL管理,以及内置大量SQL
  • 你是对代码可维护性有高要求的架构师?BeetlSQL的设计目的就是尽可能提高数据库访问代码可维护性
  • 平台级产品需要跨库,支持各种客户数据库的?BeetlSQL 支持各种库,程序员编写一次,能运行到各种数据库
  • 系统需要连接多种库,比如连接商品库,连接订单库,或者设备基本信息在MySQL,设备数据在Clickhouse里。BeetlSQL很容易支持各种库,并能一统一的方式使用
  • 系统初期单库单表,长期需要多库多表?BeetlSQL很容易实现多库多表而不需要程序员过多关注。

编译源码

git clone https://gitee.com/xiandafu/beetlsqlmvn clean packagemvn clean install #如果想修改源码

注意:BeetlSQL3 集成了Spring,以及支持大数据等,就算配置了国内镜像,也可能需要很长时间下载大数据依赖包,为了让编译快速通过,你需要进入pom.xml ,屏蔽sql-integration,sql-db-support,sql-jmh三个模块

<modules><!--核心功能 --><module>sql-core</module><module>sql-mapper</module><module>sql-util</module><module>sql-fetech</module><!-- 打包到一起 --><module>beetlsql</module><module>sql-gen</module><module>sql-test</module><module>sql-samples</module><!-- 集成和扩展太多的数据库,可以被屏蔽,以加速项目下载jar --><!--		<module>sql-integration</module>--><!--    <module>sql-jmh</module>--><!--		<module>sql-db-support</module>--></modules>

阅读源码例子

可以从模块sql-samples中找得到所有例子,或者从sql-test 中运行单元测试例子,或者在sql-integration 中的各个框架单元测试中找到相关例子。所有例子都是基于H2内存数据库,可以反复运行

sql-samples为例子

sql-samples 又包含了三个模块大约100个例子

  • quickstart: BeetlSQL基础使用例子,可以快速了解BeetlSQL3
  • usuage: BeetlSQL所有API和功能
  • plugin:BeetlSQL高级扩展实例

以usage模块为例子,包含如下代码

  • S01MapperSelectSample 15个例子, mapper中的查询演示
  • S02MapperUpdateSample 11个例子, mapper中更新操作
  • S03MapperPageSample 3个例子,mapper中的翻页查询
  • S04QuerySample 9个例子,Query查询
  • S05QueryUpdateSample 3个例子,Query完成update操作
  • S06SelectSample 14个例子,SQLManager 查询API
  • S07InsertSample 8个例子,SQLManager 插入新数据API,主键生成
  • S08UpdateSample 6个例子,更新数据
  • S09JsonMappingSample 5个例子, json配置映射
  • S10FetchSample 2个例子,关系映射
  • S11BeetlFunctionSample 2个例子,自定义sql脚本的方法

BeetlSQL提供了saga事物管理一种思路,但目前还是试验版本,欢迎不怕死的人尝试,和我一起完善这部分,其例子可以在saga模块的单元测试中找到

代码示例

例子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#selectSqlId 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有一半的注解都是通过核心注解扩展出来的

例子15 微服务事务

BeetlSQL除了集成传统的事务管理器外,也提供Saga事务支持,支持多库事务和微服务事务。 其原理是自动为每个操作提供反向操作,如insert的反向操作是deleteById,并把这些操作作为任务交给Saga—Server调度。实现了通过Kafka作为客户端(各个APP)与SagaServer 交互的媒介保证任务可靠传递并最终被系统执行。

String orderAddUrl = "http://127.0.0.1:8081/order/item/{orderId}/{userId}/{fee}";String userBalanceUpdateUrl = "http://127.0.0.1:8082/user/fee/{orderId}/{userId}/{fee}";..........SagaContext sagaContext = SagaContext.sagaContextFactory.current();try {  sagaContext.start(gid);  //模拟调用俩个微服务,订单和用户  rest.postForEntity(orderAddUrl, null,String.class, paras);  rest.postForEntity(userBalanceUpdateUrl, null,String.class, paras);  if (1 == 1) {    throw new RuntimeException("模拟失败,查询saga-server 看效果");  }} catch (Exception e) {  log.info("error " + e.getMessage());  log.info("start rollback  " + e.getMessage());  sagaContext.rollback();  return e.getMessage();}

以用户系统为例(源码是DemoController),userBalanceUpdateUrl对应如下扣费逻辑

@AutowiredUserMapper userMapper;@Transactional(propagation= Propagation.NEVER)public void update(String orderId,String userId,Integer fee){  SagaContext sagaContext = SagaContext.sagaContextFactory.current();  try{    sagaContext.start(orderId);    UserEntity  user  = userMapper.unique(userId);    user.setBalance(user.getBalance()-fee);    userMapper.upd 

鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap