BeetlSQL 企业插件库
About 1257 wordsAbout 4 min
1984-01-24
BeetlSQL插件库提供了适合企业应用的多种扩展库,目前包括
sql-accelerator
加速包,通过各种优化能让BeetlSQL性能提高50%,尽量接近手写JDBC的性能sql-bean-encrypt
字段加密包,用于企业数据脱敏sql-firewall
SQL防火墙,用于犯法不合法数据操作sql-xml
MyBatis语法支持,支持90%的mybatis XML 语法sql-dynamic-table
像操作静态表一样操作动态表,适合有动态创建表的需求sql-jooq
使用jooq生成的sql语句,用beetlsql执行
所有源码 在 https://gitee.com/xiandafu/beetlsql/tree/master/sql-ext
sql-accelerator
BeetlSQL通过此包,对BeetlSQL的性能进行提速,优化手段主要是使用字节码生成来加速属性的访问,实现类在BeanPropertyWriteFactory
public class BeanPropertyWriteFactory {
public static BeanPropertyAsm getBeanProperty(Class c){
//生成一个POJO的类属性访问类
}
}
开发者使用时候无需关心细节,只需要引入sql-accelerator
,并对SQLManager进行定制
<dependency>
<groupId>com.ibeetl</groupId>
<artifactId>sql-accelerator</artifactId>
<version>${version}</version>
</dependency>
通过PerformanceConfig类定制SQLManager
PerformanceConfig performanceConfig = new PerformanceConfig();
performanceConfig.config(sqlManager);
通过性能评测 https://gitee.com/xiandafu/beetlsql/tree/master/sql-jmh, 比较BeetlSQL和加速 BeetlSQL,以及JDBC,大多数情况下,BeetlSQL的TPS为手写JDBC的一半
Benchmark Mode Cnt Score Error Units
Beetl.addEntity thrpt 5 107.421 ± 63.432 ops/ms
Beetl.complexMapping thrpt 5 199.583 ± 291.175 ops/ms
Beetl.executeJdbcSql thrpt 5 294.096 ± 72.272 ops/ms
Beetl.executeTemplateSql thrpt 5 248.226 ± 88.204 ops/ms
Beetl.getAll thrpt 5 13.582 ± 0.590 ops/ms
Beetl.getEntity thrpt 5 324.596 ± 79.393 ops/ms
Beetl.lambdaQuery thrpt 5 172.802 ± 63.639 ops/ms
Beetl.one2Many thrpt 5 159.437 ± 130.334 ops/ms
Beetl.pageQuery thrpt 5 136.335 ± 45.815 ops/ms
Beetl.sqlFile thrpt 5 219.103 ± 46.331 ops/ms
GeneralBeetl.addEntity thrpt 5 101.724 ± 51.099 ops/ms
GeneralBeetl.complexMapping thrpt 5 195.298 ± 278.922 ops/ms
GeneralBeetl.executeJdbcSql thrpt 5 141.368 ± 41.212 ops/ms
GeneralBeetl.executeTemplateSql thrpt 5 129.438 ± 30.630 ops/ms
GeneralBeetl.getAll thrpt 5 7.889 ± 1.251 ops/ms
GeneralBeetl.getEntity thrpt 5 127.539 ± 41.250 ops/ms
GeneralBeetl.lambdaQuery thrpt 5 106.850 ± 42.768 ops/ms
GeneralBeetl.one2Many thrpt 5 128.468 ± 86.845 ops/ms
GeneralBeetl.pageQuery thrpt 5 93.118 ± 32.210 ops/ms
GeneralBeetl.sqlFile thrpt 5 134.057 ± 27.093 ops/ms
Jdbc.addEntity thrpt 5 212.159 ± 239.850 ops/ms
Jdbc.executeJdbcSql thrpt 5 661.997 ± 127.704 ops/ms
Jdbc.getAll thrpt 5 34.760 ± 9.619 ops/ms
Jdbc.getEntity thrpt 5 686.916 ± 136.272 ops/ms
sql-bean-encrypt
对字段的值在入库的时候,自动加密,出库的时候自动解密,保证数据库的值是脱敏的,参考《数据模型》安全扩展注解
BeetlSQL提供了安全扩展包支持,MD5,AES,DES等字段加密和解密
<dependency>
<groupId>com.ibeetl</groupId>
<artifactId>sql-bean-encrypt</artifactId>
<version>${version}</version>
</dependency>
使用方式举例如下,比如@MD5,或者@AES,@DES,@SM4
String code;
@MD5(saltProperty = "code")
String content;
@AES // 或者 @DES
String phone;
安全扩展包是加密注解实现了AttributeConvert接口,可以参考ql-bean-encrypt的源码或者的AttributeConvert文档编写自己的加密注解
以@AES为例子
@Retention(RetentionPolicy.RUNTIME)
@Target(value = {ElementType.METHOD, ElementType.FIELD})
@Builder(AESConvert.class)
public @interface AES {
}
@Builder说明了使用哪一个类实现此注解,类AESConvert负责,代码如下
public class AESConvert implements AttributeConvert {
@Override
public Object toDb(ExecuteContext ctx, Class cls, String name, Object pojo) {
String value= (String) BeanKit.getBeanProperty(pojo,name);
if(value==null){
return null;
}
SymmetricCrypto aes =getAes(cls,name);
String encryptData = aes.encryptHex(value);
return encryptData;
}
@Override
public Object toAttr(ExecuteContext ctx, Class cls, String name, ResultSet rs, int index) throws SQLException {
String value = rs.getString(index);
if(value==null){
return null;
}
SymmetricCrypto aes =getAes(cls,name);
String decryptData = aes.decryptStr(value);
return decryptData;
}
protected SymmetricCrypto getAes(Class cls, String name){
String key = EncryptConfig.get(EncryptType.AES);;
byte[] byteKey = SecureUtil.generateKey(SymmetricAlgorithm.AES.getValue(), key.getBytes(StandardCharsets.ISO_8859_1)).getEncoded();
SymmetricCrypto aes = SecureUtil.aes(byteKey);
return aes;
}
}
sql-firewall
SQL防火墙,用于防止一些意外操作,如删除全表
//配置
FireWall fireWall = new FireWall().setDmlCreateEnable(false).setSqlMaxLength(50);
FireWallConfig fireWallConfig = new FireWallConfig(fireWall);
fireWallConfig.config(sqlManager);
//测试
try{
String sql = "delete from order_log";
sqlManager.executeUpdate(new SQLReady(sql));
Assert.fail();
}catch (Exception exception){
Assert.assertTrue(exception instanceof BeetlSQLException);
}
注意,因为涉及到解析sql,因此有性能损耗
免责,sql-firewall并不完善,使用上造成的数据损失不应该怪BeetlSQL
sql-xml
如果你喜欢XML语法,准确的说,喜欢Mybatis语法,此扩展包提供了MyBatis的xml语法支持,具体源码和测试例子 在 https://gitee.com/xiandafu/beetlsql/tree/master/sql-ext/sql-xml/src/test
<dependency>
<groupId>com.ibeetl</groupId>
<artifactId>sql-xml</artifactId>
<version>${version}</version>
</dependency>
初始化方式如下,因此sql文件变成支持.xml方式
XMLBeetlSQL xmlBeetlSQL = new XMLBeetlSQL();
xmlBeetlSQL.config(sqlManager);
如下是一个xml文件例子,根节点是beetlsql
<?xml version="1.0" encoding="UTF-8" ?>
<beetlsql>
<sql id="testAll">
<!-- 测试sql -->
select * from sys_user
<where>
<if test="has(user) and user.name=='a'">
and name='3'
</if>
<bind value="1+99" export="newValue"/>
<isNotEmpty value="'1'">
and name='5'
</isNotEmpty>
and name = #{newValue}
and name in
<foreach items="[1,2,3]" var="id,status" open="(" close=")" separator=",">
#{id+status.index}
</foreach>
<include refid="commonWhere"/>
</where>
</sql>
<sql id="commonWhere">
and name='bdfdsf'
</sql>
<resultMap id="complexListMap">
<result property="id" column="id"/>
<collection property="listInfo" >
<result property="name" column="name"/>
<result property="age" column="age"/>
</collection>
</resultMap>
</beetlsql>
需要注意的是,beetlsql模拟了所有的myabtis xml节点(如果我遗忘了,请邮件告诉我),mybatis的表示是语法是ognl语法上,beetlsql这里采用了beetl语法,因此还是有差异,比如上面的if
,用来判断变user的name变量是否为'a',与mbatis不一样
<if test="has(user) and user.name=='a'">
mybatis是这样的
<if test=" user != null and user.name=='a'">
Beetlsql 采用了has方式,表达了user可能不存在的可能。mybatis的ongl语法则内置了了这一点
如果高度定制Beetl语法,这可以满足,比如beetl支持默认模板采用安全输出,因此也可以类似myabtsi 这样。
sql-jooq
未完成