ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
## AttributeConvert 可以自定义一个属性注解,BeetlSQL上遇到此属性注解,将按照属性注解的执行类去执行映射,比如对手机号码的入库加密,出库解密。比如对JSON对象序列化成字符串到数据库,然后从数据库反序列成成对象。同其他BeetlSQL扩展注解机制类似,实现一个扩展注解,需要使用@Builder注解申明其执行类 ```java @Retention(RetentionPolicy.RUNTIME) @Target(value = {ElementType.METHOD, ElementType.FIELD}) @Builder(Base64Convert.class) public static @interface Base64 { } ``` 如上申明一个@Base64,用于字段在入库加密,出库解密。其实现类使用@Builder注解申明,本例其执行类是Base64Convert。 执行类必须是一个AttributeConvert的子类 ```java public static class Base64Convert implements AttributeConvert { Charset utf8 = Charset.forName("UTF-8"); public Object toDb(ExecuteContext ctx, Class cls, String name, Object pojo) { String value= (String) BeanKit.getBeanProperty(pojo,name); byte[] bs = java.util.Base64.getEncoder().encode(value.getBytes(utf8)); return new String(bs,utf8); } public Object toAttr(ExecuteContext ctx, Class cls, String name, ResultSet rs, int index) throws SQLException { String value = rs.getString(index); return new String(java.util.Base64.getDecoder().decode(value),utf8); } } ``` toDb方法用于将属性转化为列,pojo是入库的POJO对象,name是指其属性名称,可以调用BeetlSQL3提供的类BeanKit.getBeanProperty获取对象属性值 toAttr将数据库转化为属性。 如下是使用@Base64的一个例子 ```java @Table(name="sys_user") @Data public class UserData{ @AutoID Integer id; @Base64 String name; } ``` 如下是定义了一个@Update注解 ```java @Retention(RetentionPolicy.RUNTIME) @Target(value = {ElementType.METHOD, ElementType.FIELD}) @Builder(UpdateTimeConvert.class) public @interface UpdateTime { } public class UpdateTimeConvert implements AttributeConvert { @Override public Object toDb(ExecuteContext ctx, Class cls,String name, Object pojo){ Date now = new Date(); BeanKit.setBeanProperty(pojo,now,name); return now; } } ``` 这样,在每次入库操作的时候,都取得最新的时间。并调用BeanKit.setBeanProperty赋值给pojo对象,并返回当前时间 。BeetlSQL3通过返回的当前时间做入库操作,因此调用BeanKit.setBeanProperty 不是必须操作。但POJO对象还需要有一个与数据库操作结果一致的值。如果未调用。pojo的对应属性为null。 源码例子org.beetl.sql.test.annotation.Jackson 是一个把对象序列化成字符串存入数据库,或者从数据库取出反序列化成对象。 ```java @Retention(RetentionPolicy.RUNTIME) @Target(value = {ElementType.METHOD, ElementType.FIELD}) @Builder(JacksonConvert.class) public @interface Jackson { } ``` JacksonConvert 实现了AttributeConvert,以toDb为例子 ```java public class JacksonConvert implements AttributeConvert { ObjectMapper objectMapper = new ObjectMapper(); @Override public Object toDb(ExecuteContext ctx, Class cls,String name, Object dbValue) { Object obj = BeanKit.getBeanProperty(dbValue,name); if(obj==null){ return null; } try { String str = objectMapper.writeValueAsString(obj); return str; } catch (JsonProcessingException e) { throw new IllegalArgumentException(...); } } } ``` AttributeConvert还能影响针对POJO自动生成的内置SQL语句,提供如下方法 ```java default String toAutoSqlPart(DBStyle dbStyle,Class cls,AutoSQLEnum autoSQLEnum, String name){ return null; } ``` 默认情况下,返回nul,不会影响自动生成语句,比如对于内置insert语句,生成的是 ```sql insert into .... value( #{id},#{jsonData} ) ``` 在postgres数据库,如果json_data列使用了jsonb,那期望内置生成的insert sql语句是 ```sql insert into .... value( #{id},#{jsonData}::JSON ) ``` 针对这个情况,可以`JacksonConvert` 可以重写toAutoSqlPart ```java default String toAutoSqlPart(DBStyle dbStyle,Class cls,AutoSQLEnum autoSQLEnum, String name){ return "$$::JSON"; } ``` 这里的$$代表了属性占位符号,BeetlSQL的内置生成sql语句依据此生成合适的sql语句,如替换`$$`,生成`#{jsonData}::JSON`. 或者替换成`?::JSON` 取决于生成方式。 可以参考源码例子 org.beetl.sql.postgres.JacksonConvert