<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          再見MybatisPlus,阿里推出新ORM框架!

          共 12972字,需瀏覽 26分鐘

           ·

          2021-08-30 05:55

          使用fluent mybatis可以不用寫具體的xml文件,通過java api可以構(gòu)造出比較復(fù)雜的業(yè)務(wù)sql語(yǔ)句,做到代碼邏輯和sql邏輯的合一。不再需要在Dao中組裝查詢或更新操作,在xml或mapper中再組裝參數(shù)。那對(duì)比原生Mybatis, Mybatis Plus或者其他框架,F(xiàn)luentMybatis提供了哪些便利呢?

          需求場(chǎng)景設(shè)置

          我們通過一個(gè)比較典型的業(yè)務(wù)需求來具體實(shí)現(xiàn)和對(duì)比下,假如有學(xué)生成績(jī)表結(jié)構(gòu)如下:

          create table `student_score`
          (
              id           bigint auto_increment comment '主鍵ID' primary key,
              student_id   bigint            not null comment '學(xué)號(hào)',
              gender_man   tinyint default 0 not null comment '性別, 0:女; 1:男',
              school_term  int               null comment '學(xué)期',
              subject      varchar(30)       null comment '學(xué)科',
              score        int               null comment '成績(jī)',
              gmt_create   datetime          not null comment '記錄創(chuàng)建時(shí)間',
              gmt_modified datetime          not null comment '記錄最后修改時(shí)間',
              is_deleted   tinyint default 0 not null comment '邏輯刪除標(biāo)識(shí)'
          ) engine = InnoDB default charset=utf8;

          現(xiàn)在有需求:

          統(tǒng)計(jì)2000年三門學(xué)科('英語(yǔ)', '數(shù)學(xué)', '語(yǔ)文')及格分?jǐn)?shù)按學(xué)期,學(xué)科統(tǒng)計(jì)最低分,最高分和平均分, 且樣本數(shù)需要大于1條,統(tǒng)計(jì)結(jié)果按學(xué)期和學(xué)科排序

          我們可以寫SQL語(yǔ)句如下

          select school_term,
                 subject,
                 count(score) as count,
                 min(score)   as min_score,
                 max(score)   as max_score,
                 avg(score)   as max_score
          from student_score
          where school_term >= 2000
            and subject in ('英語(yǔ)''數(shù)學(xué)''語(yǔ)文')
            and score >= 60
            and is_deleted = 0
          group by school_term, subject
          having count(score) > 1
          order by school_term, subject;

          那上面的需求,分別用fluent mybatis, 原生mybatis 和 Mybatis plus來實(shí)現(xiàn)一番。


          三者實(shí)現(xiàn)對(duì)比

          使用fluent mybatis 來實(shí)現(xiàn)上面的功能

          具體代碼

          https://gitee.com/fluent-mybatis/fluent-mybatis-docs/tree/master/spring-boot-demo/

          我們可以看到fluent api的能力,以及IDE對(duì)代碼的渲染效果。

          換成mybatis原生實(shí)現(xiàn)效果

          1. 定義Mapper接口

          public interface MyStudentScoreMapper {
              List<Map<String, Object>> summaryScore(SummaryQuery paras);
          }

          1. 定義接口需要用到的參數(shù)實(shí)體 SummaryQuery

          @Data
          @Accessors(chain = true)
          public class SummaryQuery {
              private Integer schoolTerm;

              private List<String> subjects;

              private Integer score;

              private Integer minCount;
          }

          1. 定義實(shí)現(xiàn)業(yè)務(wù)邏輯的mapper xml文件

          <select id="summaryScore" resultType="map" parameterType="cn.org.fluent.mybatis.springboot.demo.mapper.SummaryQuery">
              select school_term,
              subject,
              count(score) as count,
              min(score) as min_score,
              max(score) as max_score,
              avg(score) as max_score
              from student_score
              where school_term >= #{schoolTerm}
              and subject in
              <foreach collection="subjects" item="item" open="(" close=")" separator=",">
                  #{item}
              </foreach>
              and score >= #{score}
              and is_deleted = 0
              group by school_term, subject
              having count(score) > #{minCount}
              order by school_term, subject
          </select>

          1. 實(shí)現(xiàn)業(yè)務(wù)接口(這里是測(cè)試類, 實(shí)際應(yīng)用中應(yīng)該對(duì)應(yīng)Dao類)

          @RunWith(SpringRunner.class)
          @SpringBootTest(classes = QuickStartApplication.class)
          public class MybatisDemo {
              @Autowired
              private MyStudentScoreMapper mapper;

              @Test
              public void mybatis_demo() {
                  // 構(gòu)造查詢參數(shù)
                  SummaryQuery paras = new SummaryQuery()
                      .setSchoolTerm(2000)
                      .setSubjects(Arrays.asList("英語(yǔ)""數(shù)學(xué)""語(yǔ)文"))
                      .setScore(60)
                      .setMinCount(1);

                  List<Map<String, Object>> summary = mapper.summaryScore(paras);
                  System.out.println(summary);
              }
          }

          總之,直接使用mybatis,實(shí)現(xiàn)步驟還是相當(dāng)?shù)姆爆崳侍汀D菗Q成mybatis plus的效果怎樣呢?

          換成mybatis plus實(shí)現(xiàn)效果

          mybatis plus的實(shí)現(xiàn)比mybatis會(huì)簡(jiǎn)單比較多,實(shí)現(xiàn)效果如下

          如紅框圈出的,寫mybatis plus實(shí)現(xiàn)用到了比較多字符串的硬編碼(可以用Entity的get lambda方法部分代替字符串編碼)。字符串的硬編碼,會(huì)給開發(fā)同學(xué)造成不小的使用門檻,個(gè)人覺的主要有2點(diǎn):

          1. 字段名稱的記憶和敲碼困難

          2. Entity屬性跟隨數(shù)據(jù)庫(kù)字段發(fā)生變更后的運(yùn)行時(shí)錯(cuò)誤

          其他框架,比如TkMybatis在封裝和易用性上比mybatis plus要弱,就不再比較了。

          生成代碼編碼比較

          fluent mybatis生成代碼設(shè)置

          public class AppEntityGenerator {
              static final String url = "jdbc:mysql://localhost:3306/fluent_mybatis_demo?useSSL=false&useUnicode=true&characterEncoding=utf-8";

              public static void main(String[] args) {
                  FileGenerator.build(Abc.class);
              }

              @Tables(
                  /** 數(shù)據(jù)庫(kù)連接信息 **/
                  url = url, username = "root", password = "password",
                  /** Entity類parent package路徑 **/
                  basePack = "cn.org.fluent.mybatis.springboot.demo",
                  /** Entity代碼源目錄 **/
                  srcDir = "spring-boot-demo/src/main/java",
                  /** Dao代碼源目錄 **/
                  daoDir = "spring-boot-demo/src/main/java",
                  /** 如果表定義記錄創(chuàng)建,記錄修改,邏輯刪除字段 **/
                  gmtCreated = "gmt_create", gmtModified = "gmt_modified", logicDeleted = "is_deleted",
                  /** 需要生成文件的表 ( 表名稱:對(duì)應(yīng)的Entity名稱 ) **/
                  tables = @Table(value = {"student_score"})
              )
              static class Abc {
              }
          }

          mybatis plus代碼生成設(shè)置

          public class CodeGenerator {

              static String dbUrl = "jdbc:mysql://localhost:3306/fluent_mybatis_demo?useSSL=false&useUnicode=true&characterEncoding=utf-8";

              @Test
              public void generateCode() {
                  GlobalConfig config = new GlobalConfig();
                  DataSourceConfig dataSourceConfig = new DataSourceConfig();
                  dataSourceConfig.setDbType(DbType.MYSQL)
                      .setUrl(dbUrl)
                      .setUsername("root")
                      .setPassword("password")
                      .setDriverName(Driver.class.getName());
                  StrategyConfig strategyConfig = new StrategyConfig();
                  strategyConfig
                      .setCapitalMode(true)
                      .setEntityLombokModel(false)
                      .setNaming(NamingStrategy.underline_to_camel)
                      .setColumnNaming(NamingStrategy.underline_to_camel)
                      .setEntityTableFieldAnnotationEnable(true)
                      .setFieldPrefix(new String[]{"test_"})
                      .setInclude(new String[]{"student_score"})
                      .setLogicDeleteFieldName("is_deleted")
                      .setTableFillList(Arrays.asList(
                          new TableFill("gmt_create", FieldFill.INSERT),
                          new TableFill("gmt_modified", FieldFill.INSERT_UPDATE)));

                  config
                      .setActiveRecord(false)
                      .setIdType(IdType.AUTO)
                      .setOutputDir(System.getProperty("user.dir") + "/src/main/java/")
                      .setFileOverride(true);

                  new AutoGenerator().setGlobalConfig(config)
                      .setDataSource(dataSourceConfig)
                      .setStrategy(strategyConfig)
                      .setPackageInfo(
                          new PackageConfig()
                              .setParent("com.mp.demo")
                              .setController("controller")
                              .setEntity("entity")
                      ).execute();
              }
          }


          FluentMybatis特性一覽

          三者對(duì)比總結(jié)

          看完3個(gè)框架對(duì)同一個(gè)功能點(diǎn)的實(shí)現(xiàn), 各位看官肯定會(huì)有自己的判斷,筆者這里也總結(jié)了一份比較。

          -Mybatis PlusFluent Mybatis
          代碼生成生成 Entity生成Entity, 再通過編譯生成 Mapper, Query, Update 和 SqlProvider
          Generator易用性
          和Mybatis的共生關(guān)系需替換原有的SqlSessionFactoryBean對(duì)Mybatis沒有任何修改,原來怎么用還是怎么用
          動(dòng)態(tài)SQL構(gòu)造方式應(yīng)用啟動(dòng)時(shí), 根據(jù)Entity注解信息構(gòu)造動(dòng)態(tài)xml片段,注入到Mybatis解析器應(yīng)用編譯時(shí),根據(jù)Entity注解,編譯生成對(duì)應(yīng)方法的SqlProvider,利用mybatis的Mapper上@InsertProvider @SelectProvider @UpdateProvider注解關(guān)聯(lián)
          動(dòng)態(tài)SQL結(jié)果是否容易DEBUG跟蹤不容易debug容易,直接定位到SQLProvider方法上,設(shè)置斷點(diǎn)即可
          動(dòng)態(tài)SQL構(gòu)造通過硬編碼字段名稱, 或者利用Entity的get方法的lambda表達(dá)式通過編譯手段生成對(duì)應(yīng)的方法名,直接調(diào)用方法即可
          字段變更后的錯(cuò)誤發(fā)現(xiàn)通過get方法的lambda表達(dá)的可以編譯發(fā)現(xiàn),通過字段編碼的無法編譯發(fā)現(xiàn)編譯時(shí)便可發(fā)現(xiàn)
          不同字段動(dòng)態(tài)SQL構(gòu)造方法通過接口參數(shù)方式通過接口名稱方式, FluentAPI的編碼效率更高
          語(yǔ)法渲染特點(diǎn)通過關(guān)鍵變量select, update, set, and, or可以利用IDE語(yǔ)法渲染, 可讀性更高


            作者 |  稻草江南

          來源 |  juejin.cn/post/6886019929519177735

          加鋒哥微信: java3459  
          圍觀鋒哥朋友圈,每天推送Java干貨!

          瀏覽 46
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日韩AV中文字幕在线播放 | 18禁日韩无码 | 国产日韩欧美一区二区东京热 | 欧亚免费视频 | 人人摸人人 |