为什么推荐选择Mybatis Dynamic SQL

为什么选择Mybatis Dynamic SQL?

MBG已经推荐所有的java新项目,都采用Mybatis Dynamic SQL,以java API的方式书写SQL,而不是XML。

This is the default runtime. It is the recommended runtime for all new Java projects

实践总结

1. 代码量少很多。一行流式代码即可完成,无需臃肿的example用法

2. 0 XML,再也不用和XML打交道

  • 不存在XML的SQL注入风险。Fortify安全扫描中,再也不会被安全漏洞所困扰;
  • 不存在重构风险。过去重构代码时,IDE会忽略掉XML中的对应信息,导致重构不完整,出现软件错误;新的方式全基于JAVA,IDE重构完整;
  • 不存在自定义的mapper函数难以找到XML内定义SQL问题。原来需要手动去XML查找,无法借IDE之力。新的方式由于全基于JAVA,IDE可以直接找到自定义的SQL
  • 不存在自定义SQL的语法错问题。原来XML的方式是手写SQL,且需要填jdbcType,列信息等繁琐配置,且无法避免错误语法问题。新的方式基于JAVA API,不存在手写SQL导致的潜在语法问题。
  • 少了额外的XML,生成的文件更少,让注意力更聚焦;

3. 比基于XML生成的example系列通用函数更全

  • 终于具备非常常用的批量插入了(insertMultiple)
  • 也可以直接使用万能的select函数了(不再担心XML的selectByExample函数涉及安全风险,而不敢生成,导致简单的select函数都要自定义的搞笑事情)

4. 自定义的mapper可以继承通用mapper。原来XML的方式,自定义的mapper和生成的通用mapper是2个独立的接口,无法使用继承,否则会出现多个bean的错误。新的方式,自定义mapper可以继承生成的通用mapper,全局只需要一个自定义的mapper的bean即可。

代码对比

通用场景
旧的基于XML的Criteria模式
        SparringWorkflowNodeEntityExample example = new SparringWorkflowNodeEntityExample();
        SparringWorkflowNodeEntityExample.Criteria criteria = example.createCriteria();
        criteria.andDeleteFlagEqualTo(0);
        criteria.andWorkflowIdEqualTo(lessonId);
        example.setOrderByClause("sequence_number ASC");
        List<SparringWorkflowNode> workflowNodeEntities = sparringWorkflowNodeEntityMapper.selectByExample(example);

新的基于JAVA API的流式模式
List<SparringWorkflowNode> workflowNodeEntities = sparringWorkflowNodeMapper.select(c->c.where(deleteFlag, isEqualTo(0)).and(workflowId, isEqualTo(lessonId)).orderBy(sequenceNumber));

实践细节

MBG的配置文件

generator-configuration.xml这个文件,targetRuntime="MyBatis3DynamicSql" 这是最关键的配置,决定了这是基于JAVA API的Dynamic SQL的方式。

通用Mapper

自定义Mapper

对于无法使用通用mapper的场景,可以使用自定义的方式。

自定义一个接口,继承通用mapper(这样可以无需使用2个bean)

@Mapper
public interface SparringWorkflowMapperCustomized extends SparringWorkflowMapper {
    @TimeIt
    @SelectProvider(value = WorkflowSqlBuilder.class, method = "searchWorkflowVectorSimple")
    List<SparringWorkflow> searchWorkflowSimple(String query, ESparringWorkflowType workflowType, String account);

    @SelectProvider(value = WorkflowSqlBuilder.class, method = "getStudentAllLessons")
    List<SparringWorkflow> getStudentAllLessons(ESparringWorkflowType workflowType, String account);

}

通过Mybatis的JAVA API 定义SQL (可以参考Mybatis 官方 mybatis – MyBatis 3 | SQL 语句构建器

@Slf4j
public class WorkflowSqlBuilder {
    final static String TABLE_NAME = "sparring_workflow";
    final static String WEIGHT_VECTOR = "(setweight(to_tsvector('zh', workflow_name), 'A') ||  setweight(to_tsvector('zh', workflow_desc), 'C'))";
    public static String searchWorkflowVectorSimple(final String query, final ESparringWorkflowType workflowType, final String account){
        return new SQL(){{
            SELECT(" * ");
            FROM(String.format("%s, websearch_to_tsquery('zh', #{query}) search, ts_rank_cd(%s, search, 1) rank", TABLE_NAME, WEIGHT_VECTOR));
            WHERE(WEIGHT_VECTOR + " @@ search");
            WHERE("delete_flag = 0");
            if(workflowType != null){
                WHERE("workflow_type = #{workflowType.code}");  //mybatis会寻找code这个field的getter,实际执行的是workflowType.getCode()
            }
            /*
            在sql中,jsonb后面只有一个?,但是由于mybatis也使用?作为未知参数,会出现错误。因此,这里采用??等价sql里的?
             */
            if(Strings.isNotBlank(account)){
                WHERE("users::jsonb??#{account}");
            }
            ORDER_BY("rank DESC");
        }}.toString();
    }

    public static String getStudentAllLessons(final ESparringWorkflowType workflowType, final String account){
        return new SQL(){{
            SELECT("*");
            FROM(TABLE_NAME);
            WHERE("delete_flag = 0");
            if(workflowType != null){
                WHERE("workflow_type=#{workflowType.code}");
            }
            if(Strings.isNotBlank(account)){
                WHERE("users::jsonb??#{account}");
            }
            ORDER_BY("updated_date DESC");

        }}.toString();
    }

}

  • 24
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Mybatis动态SQL是指在Mybatis框架中,根据不同的条件动态生成SQL语句的技术。通过使用Mybatis提供的动态SQL标签,可以根据不同的条件生成不同的SQL语句,从而实现更加灵活的数据查询和操作。动态SQL标签包括if、choose、when、otherwise、foreach等,可以根据需要灵活组合使用,生成符合要求的SQL语句。 ### 回答2: MyBatis动态SQL是一个非常有用的功能,它可以使开发人员在运行期间修改或组合SQL语句。通过使用这种方法,开发人员可以在不同情况下生成不同的SQL语句,从而使应用程序更加灵活。它的主要优点是减少代码重复,提高代码组织的可读性和代码的重用性。在一些需要在运行时动态生成SQL的情况下,这种方式显得尤为重要。 MyBatis动态SQL可以用在许多场景中,例如根据条件查询不同的结果集、动态生成表名等。MyBatis动态SQL的实现,可以借助属性检查器和OGNL表达式编辑器,还可以选用标签库中的if、where、foreach、choose等标签实现。在实际开发中,一些情况下需要动态构建SQL,比如: 1. 动态构建查询条件。通过使用where标签,可以根据输入参数的不同来拼接查询语句。 2. 动态构建排序条件。通过使用orderBy标签,可以根据不同的排序条件来动态构建排序语句。 3. 动态构建更新语句。通过使用set标签,可以根据不同的更新操作来动态构建更新语句。 4. 动态构建插入语句。通过使用foreach标签,可以根据不同的输入参数来动态构建插入语句。 5. 动态构建删除语句。通过使用if标签,可以根据不同的条件来动态构建删除语句。 总而言之,MyBatis动态SQL是一种强大的功能,可以提高我们代码的复用性和可维护性。它可以帮助我们快速构建灵活的SQL语句,并且能够适应不同的业务需求。因此,在编写MyBatis应用程序时,我们应该充分发挥这种功能的优势,提高我们的开发效率和代码质量。 ### 回答3: MyBatis动态SQL是通过MyBatis提供的特殊语法编写灵活且可重用的SQL语句。它利用了MyBatis强大的type handler机制和基于OGNL的表达式语言,可以方便地实现各种业务需求。 动态SQL允许我们基于不同的条件和参数来生成动态的SQL语句,从而实现灵活的查询和操作,常见的动态SQL语句包括IF、WHERE、TRIM、CHOOSE等。其中,IF语句可以根据传入的参数来判断是否包含某一部分SQL语句,WHERE语句可以构建WHERE子句,并自动处理AND和OR的逻辑关系,TRIM语句可以动态去除SQL语句中的空格和逗号,CHOOSE语句可以根据传入的参数选择不同的查询语句。 除了基本的动态SQL语句外,MyBatis还提供了foreach语句,它可以帮助我们循环处理集合类型的参数,并自动生成对应数量的占位符和参数列表。此外,MyBatis还可以通过继承BaseMapper接口并使用@SqlProvider注解自动生成CRUD操作的SQL语句,从而避免手动编写大量相似的SQL语句,并提高代码的可维护性和重用性。 总之,MyBatis动态SQL是一种强大的语法,可以方便地生成灵活、可重用的SQL语句,避免了大量重复劳动和错误。如果你掌握了MyBatis动态SQL的使用,相信会极大地提高你的开发效率和代码质量。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值