开发框架搭建考量( 二 )

// Mapper
@SelectProvider(type = IssueProvider.class, method = "list")
Page<IssueVO> list(IssueVO issue);
// Provider
// Issue是对应的Bean,字段调整后,在Issue中添加对应的字段即可(可以生成,可以手动添加)
public String list(Issue issue) {
SQL sql = new SQL();
sql.SELECT("*");
sql.FROM("issue");
BeanMap beanMap = BeanMap.create(issue);
for (Object key : beanMap.keySet()) {
Object val = beanMap.get(key);
if (val != null) {
if (val instanceof String && ((String) val).contains("%")) {
sql.WHERE("`" + FieldUtils.camelToLine(key + "") + "`" + "like #{" + key + "}");
} else {
sql.WHERE("`" + FieldUtils.camelToLine(key + "") + "`" + "=#{" + key + "}");
}
}
}
return sql.toString();
}
  • 优势:
    • 改动量比较小
  • 劣势:
    • 反射对性能的影响
    • 基于注解的方式,习惯性问题
    • IDEA对Provider的方式的支持没有XML高,XML支持自动完成,Provider中不支持
基于Mapper接口继承
  • Mybatis生成的Mapper和XML文件分别为独立的目录
  • 自定义的Mapper继承生成的Mapper,在自定义Mapper中新增自定义接口方法,对应的sql添加到对应的自定义XML文件中
  • 自定义XML文件可以基于NameSpace来使用生成的XML文件的Result
  • 当表结构调整后,重新生成对应的Mapper和XML即可
  • 优势:
    • 符合习惯
  • 劣势:
    • 改动量相对多一点,不过是生成的,所以基本可以忽略
复杂关系精简化一般项目中的库表设计基本都是按照关联表的方式进行设计的:
  • 主表+子表的关联关系
  • 表中冗余其它表的字段
可以结合场景考虑,做一些结构简化和结构化 。简化为对单表的操作,可以基于上面的模板来自动生成代码 。
主表+子表的关联关系此种方式适用于主表和子表需要单独修改的场景 。如果主表和子表是聚合关系,即子表依赖于主表存在,且需要一起调整,甚至子表不需要调整,实际可以简化此种关联关系 。
因为此种关联关系涉及到了联表查询,联表查询是无法基于工具生成的 。通过简化此种关系,可以基于工具来提高开发效率 。
表中冗余其它表的字段有些情况下,可能会将两个逻辑上分离的对象整合为一个对象来处理,简化操作负责度 。例如订单中可能直接就包含购买的应用信息 。此种情况实际是为了操作的便利性,同时兼顾数据库特性,将结构化的数据扁平化了 。
数据扁平化本身问题不大,不过弱化了代码语义 。在正常理解里,订单包含订单明细,订单明细中是商品信息 。
可以通过下面的方法来解决上面提到的两个问题 。
解决方案MySQL5.7开始支持Json 。上述两种情况,都可以基于Json的方式来处理 。即数据库字段可以使用json类型 。
// 支持基于json的查询,请自行google
create table order
(
......
item_info_json json not null comment 'json',
);
public class Order {
private ItemInfo itemInfoJson;
}
在Mybatis层面,通过TypeHandler来处理Json与对象之间的自动转换 。
public interface OrderDao {
// 配置转换handler
@Results(id = "jsonResult", value = https://www.isolves.com/it/cxkf/kj/2020-11-16/{
@Result(property = "itemInfoJson", column = "item_info_json", typeHandler = JsonTypeHandler.class)
})
@Select("select * from order where rec_id = #{recId}")
Order selectByPrimaryKey(@Param("recId") String recId);
@InsertProvider(type = OrderProvider.class, method = "insert")
void insert(Order model);
 
......
}
 
public class OrderProvider {
public String insert(Order order) {
SQL sql = new SQL();
sql.INSERT_INTO("order");
BeanMap beanMap = BeanMap.create(order);
for (Object key : beanMap.keySet()) {
Object val = beanMap.get(key);
if (val != null) {
if ((key + "").endsWith("Json")) { // 根据后缀判定是否需要转换
sql.VALUES("`" + FieldUtils.camelToLine(key + "") + "`", "#{" + key + ", typeHandler=com.iwhalecloud.common.mybatis.JsonTypeHandler}");
} else {
sql.VALUES("`" + FieldUtils.camelToLine(key + "") + "`", "#{" + key + "}");


推荐阅读