一个支持动态配置、ORM、SQL 重构、跨数据库的 Java 持久层工具。
1jSqlBox 是什么?
jSqlBox 是一个微型的、易学易用的、支持简单的 O-R 映射的持久层工具,目标是用来代替功能强大但过于复杂的 Hibernate,以及一些相对简单但功能不尽人意的持久层工具如MyBatis / JDBC / JDBCTemplate / DButils / EBean / OpenJPA / jFinal / jActiveRecord / ActiveJDBC / JOOQ / BeetlSQL / NutzDao 等。目前 jSqlBox 项目尚未完全开发完成,欢迎有兴趣者试用或加入开发组。
一张对比图显示 jSqlBox 项目的定位和开发目标:(打分仅为个人看法,0 到 5 分制, 0~5分,X 号表示重大缺陷,只要有 X 号即不推荐使用) 。
上表只是对软件架构方面的一个比较。速度、可靠性、开发进度、日志、文档、覆盖测试等指标不在比较范围内,因为开源项目用的人多了,这些属于软件质量上的问题自然会日益改进,但是如果因为设计思路的问题,造成易用性和可维护性上存在缺陷,则无论怎样改进软件质量也是无法弥补的。
2为什么要开发jSqlBox?
因为作者发现了一种利用 Java 初始块来代替 XML 和 Annotation 配置的方法(即"BOX"模式,详见 jBeanBox 项目),凡是利用 XML 和 Annotation 作为配置文件的项目,都存在着 XML 和 Annotation 不够灵活,配置文件不能动态生成、修改的问题,这对于需要动态生成或修改配置的场合是个致命缺陷。作者在完成 jBeanBox 项目后,发现 Hibernate 和 MyBatiis 这两个流行的持久层工具也都存在这个问题,这是 jSqlBox 项目产生的原因。简单说, jSqlBox 的开发目标就是一个支持动态配置的持久化工具。这是一个先有了锤子,再找钉子的项目, Hiberante 和 MyBatis 就是这个项目的两个钉子。
开发之前,作者研究了 Hibernate 存在的一些问题,主要归纳如下:
如前所述,配置是固定的,不能动态变化,对于需要在运行期动态创建或改变数据源、数据表、列名、映射方式的场合,解决起来比较麻烦。
缺省情况下,实体类为容器管理,导致任何对 PO 的更改都会写入数据库,这使得 PO 不能与 VO 共享字段, PO 不能当成 VO 简单地传递到 View 层使用。
HQL 语言是对 SQL 的包装,属于重新发明轮子,虽然 HQL 是操纵对象的,但是具有讽刺意味的是:HQL 语言本身不是面向对象的,不支持 IDE 拼写检查和重构。(顺便说一下 MyBatis 和 BeetlSql 这个两个项目,前者将 SQL 写在 XML 中,后者将 SQL 写在模板语言中,虽然灵活性较高,可以自定义一些特殊语法,但是 IDE 的重构功能对于 XML 和模板语言不起作用,一旦数据库字段变动,将不得不手工检查和修改大量 SQL,这是一个繁重且可能出错的工作。)
过度复杂,源码庞大(超过 3 千个类)。虽然号称无侵入的轻量级框架,但 HQL 和实体管理容器本身就是一种入侵,采用了这种架构的项目就绑死在了实体容器这种复杂的工具上了。 jSqlBox 虽然最初目的是给 Hibernate 加一个动态配置,但考虑到实体容器开发及使用的复杂性,以及个人水平有限,借鉴了 MyBatis 的做法,即在运行期如需用到 OR 映射时,在程序中动态配置并完成 OR 转换。与 MyBatis 不同的是 jSqlBox 在易用性上作了极大改进,取消了繁琐的 XML 配置和注解,简单的 CRUD 之类 SQL 更不必手工创建。与目前流行的一些小众持久层工具相比, jSqlBox 则胜在体积虽小功能齐全,例如:无 XML、无注解、动态配置、CRUD 方法、ORM、动态关联、越级查找关联、跨数据库、分页、多种主键生成、对象及查询缓存、支持 SQL重构、首创 SQL 内直接写参数等,很多微型持久层工具都缺少若干项这些对易用性、可维护性非常关键的特性。
3主要特点
简单,目前只有约 30个 Java 类,是一个能够轻松架驭的微型工具,学习、维护、二次开发都很容易。 提供 CRUD 方法,简单的 CRUD 操作占持久层大半的工作量,对一个持久层工具来说自动生成 CRUD 方法是必须提供的基本功能。 基于 ActiveRecord 模式,无 Session 的显式注入。支持多上下文。但当仅有一个数据源时,鼓励运用全局缺省上下文来简化配置。 低侵入,PO 类只需要声明实现 Entity 接口即可(仅适用于 Java8 及以上,对于 Java 7及以下需要继承自 EntityBase 基类)。 没有 XML,没有注解,没有脚本,没有模板语言,具有静态语言特性的 Java 本身就是一种完美的配置文件,它强大、灵活、面向对象、支持IDE 拼写检查和重构,飞速启动(因为已经编译成字节码,无需象 XML 那样在运行期解析)。 不重新发明 SQL 语法,直接使用原生 SQL。 对 SQL 的包装, jSqlBox 首创利用 ThreadLocal 将字符串拼接的 SQL 参数自动包装成 preparedStatement,防止 SQL 注入,精简代码,提高可维护性。 支持原生 SQL 重构。数据库列名变动、PO 类字段变动等借由 IDE 的重构功能来管理,不需要手工检查已存在的 SQL,保证了 SQL 的健壮性。 无配置,默认按 Java Bean 命名规则,PO 类自动适应数据库表,字段自动
匹配驼峰式或下划线式数据表列名,无需配置。 可配置,当数据库表名、字段名与缺省匹配规则不一致时,可用配置的方式来解决,配置为同目录或内嵌的"类名+Box"的 Java 类,也可将配置写在类初始化块中。 多配置和动态配置,同一个 PO 可采用不同的配置以进行多种方式的存取,配置可以继承重用已有的配置,配置可以在运行期动态生成和修改,与 jBeanBox 项目配置类似。 支持多种主键生成方式,与 Hibernate / JPA 类似,目前支持 9 种主键生成方式,也可自定义主键生成类。 (开发中)一级缓存与脏检查,与 Hibernate 类似,提供以 ID 为主键的行级缓存,一级缓存在跨越多个方法的同一事务中有效,对 PO 的存取不再重复访问数据库。与 Hibernate 的区别在于 jSqlBox 一级缓存比较简单,只缓存实体,包括已修改过的,不缓存 SQL命令。 (开发中)二级缓存和查询缓存,类似于 Hibernate 的缓存设计,可配置第三方缓存工具如 EHcache 等。 支持多主键,适于使用了业务多主键的数据库。 跨数据库,目前已在 H2,MySql,SqlServer,Oracle 上测试过,今后将加入更多的数据库支持。事务借用 Spring 的声明式事务。一些特殊的需求可以通过直接调用内核的 JdbcTemplate 来实现,内核建立在 JdbcTemplate 上倒不是作者对 Spring 有偏爱,而是因为它的声明式事务比较好用,目前找不到其它的 JDBC 类底层工具可以提供类似 Spring 的声明式事务。 不使用代理类,不会有代理类造成的希奇古怪的问题。没有懒加载,也就没有 OpenSessionInView问题, PO 类可以直接充当 VO 传递到 View 层, PO 在 View 层事务已关闭情况下,依然可以继续存取数据库(工作在自动提交模式,但通常只读)。 提供简单的 O-R 映射,有一对一,一对多,树结构三种映射类型,多对多可由两个一对多组合成。支持固定、动态关联和越级自动查找关联功能。 跨数据库的分页支持 4jSqlBox缺点
比较新,缺少足够测试、文档、缺少开发和试用者(欢迎在个人项目中试用或加入开发组,任何问题和建议都会促使它不断完善)。
实体映射比较简单,只限于将数据集内容装配成对象树,不支持多重嵌套映射和懒加载,需要懒加载的场合须由用户自行在程序中手工实现。或利用 jSqlBox 的无绑定关联来从根本上避免懒加载需求的出现。
暂不支持 Blob,Clob 类型的包装,待今后版本加入,目前可利用内核的 JDBCTemplate 来进行 Blob,Clob 字段的存取。
暂无分库、分表、读写分离等功能,但对于 jSqlBox 这种以支持动态配置为卖点的持久层工具来说,以上功能应不难实现,将来可能作为测试示例加入。