Skip to content
  • Home
  • Python教學
  • 科技新聞資訊
  • 網站開發教學
Copyright 網絡設計教學 2025
Theme by ThemeinProgress
Proudly powered by WordPress
  • Home
  • Python教學
  • 科技新聞資訊
  • 網站開發教學
網絡設計教學網絡設計教學,網站網頁教學,軟體使用教學
  • You are here :
  • Home
  • 網站開發教學
  • 全新Logo,Mybatis-Flex v1.0 正式版發布- 科技資訊
網站開發教學

全新Logo,Mybatis-Flex v1.0 正式版發布- 科技資訊

Jiking 2023-03-13 Article

Mybatis-Flex v1.0 正式版發布了,意味著我們可以在我們的正式項目上開始使用Mybatis-Flex, v1.0 正式版的推出,同時伴隨出來的還有著大量的測試和文檔,所以,放心使用。 Mybatis-Flex 的目標是成為全網最好用的Mybatis 增強框架,讓Mybatis 飛起來。這也是這個LOGO 的含義。

特徵

  • 1、很輕量,整個框架只依賴Mybatis 再無其他第三方依賴。
  • 2、只增強,支持Entity 的增刪改查、及分頁查詢,但不丟失Mybatis 原有功能
  • 3、內置Db + Row 工具,可以無需實體類對數據庫進行增刪改查
  • 4、支持多種數據庫類型,還可以通過方言持續擴展
  • 5、支持多(聯合)主鍵,以及不同的主鍵內容生成策略
  • 6、支持邏輯刪除設置、更新或插入的默認值配置以及大字段等設置
  • 7、支持樂觀鎖字段配置,在數據更新時自動進行樂觀鎖檢測
  • 8、極其友好的SQL 聯動查詢,IDE 自動提示不再擔心出錯
  • 9、更多小驚喜

在第一點中,Mybatis-Flex 很輕,除了沒有依賴任何第三方框架以外,Mybatis-Flex 的增強實現方式很輕,沒有任何攔截器、沒有任何改寫SQL 和Sql parse,全部都是基於Mybatis 官方推薦的SqlProvider 的方式實現,所以在程式碼調試、跟進都是顯而易見的。

Mybatis-Flex 沒有使用Lambda 表達式,除了通過使用“方法名稱” 代表“字段” 顯得怪異以外,通過Lambda 表達式推導出“字段” 的代價也是巨大的。

開始

hello world(原生)

第一步:編寫Entity 實體類


@Table("tb_account")
public class Account {

    @Id(keyTYpe = KeyType.Auto)
    private Long id;
    private String userName;
    private Date birthday;
    private int sex;

    //getter setter
}

第二步,編寫Mapper 類,並繼承BaseMapper


public interface AccountMapper extends BaseMapper<Account> {
    //只需定义 Mapper 接口即可,可以无任何内容。
}

第三步:開始查詢數據

示例1:查詢1 條數據


class HelloWorld {
    public static void main(String... args) {

        HikariDataSource dataSource = new HikariDataSource();
        dataSource.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/mybatis-flex");
        dataSource.setUsername("username");
        dataSource.setPassword("password");

        MybatisFlexBootstrap.getInstance()
                .setDatasource(dataSource)
                .addMapper(AccountMapper.class)
                .start();


        //示例1:查询 id=100 条数据
        Account account = MybatisFlexBootstrap.getInstance()
                .execute(AccountMapper.class, mapper ->
                        mapper.selectOneById(100)
                );
    }
}

示例2:查詢列表


//示例2:通过 QueryWrapper 构建条件查询数据列表
QueryWrapper query=QueryWrapper.create()
    .select()
    .from(ACCOUNT)
    .where(ACCOUNT.ID.ge(100))
    .and(ACCOUNT.USER_NAME.like("张").or(ACCOUNT.USER_NAME.like("李")));

// 执行 SQL:
// ELECT * FROM `tb_account`
// WHERE `tb_account`.`id` >=  100
// AND (`tb_account`.`user_name` LIKE '%张%' OR `tb_account`.`user_name` LIKE '%李%' )
List<Account> accounts=MybatisFlexBootstrap.getInstance()
    .execute(AccountMapper.class,mapper->
        mapper.selectListByQuery(query)
    );

示例3:分頁查詢


// 示例3:分页查询
// 查询第 5 页,每页 10 条数据,通过 QueryWrapper 构建条件查询
QueryWrapper query=QueryWrapper.create()
    .select()
    .from(ACCOUNT)
    .where(ACCOUNT.ID.ge(100))
    .and(ACCOUNT.USER_NAME.like("张").or(ACCOUNT.USER_NAME.like("李")))
    .orderBy(ACCOUNT.ID.desc());

// 执行 SQL:
// ELECT * FROM `tb_account`
// WHERE `id` >=  100
// AND (`user_name` LIKE '%张%' OR `user_name` LIKE '%李%' )
// ORDER BY `id` DESC
// LIMIT 40,10
Page<Account> accounts=MybatisFlexBootstrap.getInstance()
.execute(AccountMapper.class,mapper->
    mapper.paginate(5,10,query)
);

QueryWrapper 示例

select *


QueryWrapper query=new QueryWrapper();
query.select().from(ACCOUNT)

// SQL: 
// SELECT * FROM tb_account

select columns


QueryWrapper query=new QueryWrapper();
query.select(ACCOUNT.ID,ACCOUNT.USER_NAME)
    .from(ACCOUNT)

// SQL: 
// SELECT id, user_name 
// FROM tb_account


QueryWrapper query=new QueryWrapper();
query.select(ACCOUNT.ALL_COLUMNS).from(ACCOUNT)

// SQL: 
// SELECT id, user_name, birthday, sex, is_normal 
// FROM tb_account

select functions


QueryWrapper query=new QueryWrapper()
    .select(
        ACCOUNT.ID,
        ACCOUNT.USER_NAME,
        max(ACCOUNT.BIRTHDAY),
        avg(ACCOUNT.SEX).as("sex_avg")
    ).from(ACCOUNT);

// SQL: 
// SELECT id, user_name, 
// MAX(birthday), 
// AVG(sex) AS sex_avg 
// FROM tb_account

where


QueryWrapper queryWrapper=QueryWrapper.create()
    .select()
    .from(ACCOUNT)
    .where(ACCOUNT.ID.ge(100))
    .and(ACCOUNT.USER_NAME.like("michael"));

// SQL: 
// SELECT * FROM tb_account 
// WHERE id >=  ?  
// AND user_name LIKE  ? 

where select


QueryWrapper queryWrapper = QueryWrapper.create()
    .select()
    .from(ACCOUNT)
    .where(ACCOUNT.ID.ge(
       select(ARTICLE.ACCOUNT_ID).from(ARTICLE).where(ARTICLE.ID.ge(100))
    ));

// SQL: 
// SELECT * FROM `tb_account` 
// WHERE `id` >= 
// (SELECT `account_id` FROM `tb_article` WHERE `id` >=  ? )

exists, not exists


QueryWrapper queryWrapper=QueryWrapper.create()
    .select()
    .from(ACCOUNT)
    .where(ACCOUNT.ID.ge(100))
    .and(
        exist(
            selectOne().from(ARTICLE).where(ARTICLE.ID.ge(100))
        )
    );

// SQL: 
// SELECT * FROM tb_account 
// WHERE id >=  ?  
// AND EXIST (
//    SELECT 1 FROM tb_article WHERE id >=  ? 
// )

and (…) or (…)


QueryWrapper queryWrapper=QueryWrapper.create()
    .select()
    .from(ACCOUNT)
    .where(ACCOUNT.ID.ge(100))
    .and(ACCOUNT.SEX.eq(1).or(ACCOUNT.SEX.eq(2)))
    .or(ACCOUNT.AGE.in(18,19,20).and(ACCOUNT.USER_NAME.like("michael")));

// SQL: 
// SELECT * FROM tb_account 
// WHERE id >=  ?  
// AND (sex =  ? OR sex =  ? ) 
// OR (age IN (?,?,?) AND user_name LIKE ? )

group by


QueryWrapper queryWrapper=QueryWrapper.create()
    .select()
    .from(ACCOUNT)
    .groupBy(ACCOUNT.USER_NAME);

// SQL: 
// SELECT * FROM tb_account 
// GROUP BY user_name

having


QueryWrapper queryWrapper=QueryWrapper.create()
    .select()
    .from(ACCOUNT)
    .groupBy(ACCOUNT.USER_NAME)
    .having(ACCOUNT.AGE.between(18,25));

// SQL: 
// SELECT * FROM tb_account 
// GROUP BY user_name 
// HAVING age BETWEEN  ? AND ?

orderBy


QueryWrapper queryWrapper=QueryWrapper.create()
    .select()
    .from(ACCOUNT)
    .orderBy(ACCOUNT.AGE.asc()
        , ACCOUNT.USER_NAME.desc().nullsLast());

// SQL: 
// SELECT * FROM `tb_account` 
// ORDER BY `age` ASC, `user_name` DESC NULLS LAST

join


QueryWrapper queryWrapper=QueryWrapper.create()
    .select()
    .from(ACCOUNT)
    .leftJoin(ARTICLE).on(ACCOUNT.ID.eq(ARTICLE.ACCOUNT_ID))
    .innerJoin(ARTICLE).on(ACCOUNT.ID.eq(ARTICLE.ACCOUNT_ID))
    .where(ACCOUNT.AGE.ge(10));

// SQL: 
// SELECT * FROM tb_account 
// LEFT JOIN tb_article ON tb_account.id = tb_article.account_id 
// INNER JOIN tb_article ON tb_account.id = tb_article.account_id 
// WHERE tb_account.age >=  ?

limit… offset


QueryWrapper queryWrapper = QueryWrapper.create()
    .select()
    .from(ACCOUNT)
    .orderBy(ACCOUNT.ID.desc())
    .limit(10)
    .offset(20);

// MySql: 
// SELECT * FROM `tb_account` ORDER BY `id` DESC LIMIT 20, 10

// postgreSQL: 
// SELECT * FROM "tb_account" ORDER BY "id" DESC LIMIT 20 OFFSET 10

// informix: 
// SELECT SKIP 20 FIRST 10 * FROM "tb_account" ORDER BY "id" DESC

// oracle: 
// SELECT * FROM (SELECT TEMP_DATAS.*, 
//  ROWNUM RN FROM (
//          SELECT * FROM "tb_account" ORDER BY "id" DESC) 
//      TEMP_DATAS WHERE  ROWNUM <=30) 
//  WHERE RN >20

// db2: 
// SELECT * FROM "tb_account" ORDER BY "id" DESC 
// OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY

// sybase: 
// SELECT TOP 10 START AT 21 * FROM "tb_account" ORDER BY "id" DESC

// firebird: 
// SELECT * FROM "tb_account" ORDER BY "id" DESC ROWS 20 TO 30

在以上的”limit… offset” 示例中,Mybatis-Flex 能夠自動識別當前數據庫,並生成不同的SQL,用戶也可以很輕易的通過 DialectFactory 註冊(新增或改寫)自己的實現方言。

存在疑問?

疑問1:QueryWrapper 是否可以在分佈式項目中通過RPC 傳輸?

答:可以。

疑問2:如何通過實體類Account.java 生成QueryWrapper 所需要的”ACCOUNT” 類 ?

答:Mybatis-Flex 使用了APT(Annotation Processing Tool)技術,在項目編譯的時候,會自動根據Entity 類定義的字段幫你生成”ACCOUNT” 類, 通過開發工具構建項目(如下圖),或者執行maven 編譯命令: mvn clean package 都可以自動生成。這個原理和lombok 一致。

更多關於Mybatis-Flex APT 的配置,請點擊 這裡。

Db + Row 工具類

Db + Row 工具類,提供了在Entity 實體類之外的數據庫操作能力。使用Db + Row 時,無需對數據庫表進行映射, Row 是一個HashMap 的子類,相當於一個通用的Entity。以下為Db + Row 的一些示例:


//使用原生 SQL 插入数据
String sql="insert into tb_account(id,name) value (?, ?)";
Db.insertBySql(sql,1,"michael");

//使用 Row 插入数据
Row account=new Row();
account.set("id",100);
account.set("name","Michael");
Db.insertRow("tb_account",account);


//根据主键查询数据
Row row=Db.selectOneById("tb_account","id",1);

//Row 可以直接转换为 Entity 实体类,且性能极高
Account account=row.toEntity(Account.class);


//查询所有大于 18 岁的用户
String listsql="select * from tb_account where age > ?"
List<Row> rows=Db.selectListBySql(sql,18);


//分页查询:每页 10 条数据,查询第 3 页的年龄大于 18 的用户
QueryWrapper query=QueryWrapper.create()
.where(ACCOUNT.AGE.ge(18));
Page<Row> rowPage=Db.paginate("tb_account",3,10,query);

Db 工具類還提供了更多增、刪、改、查和分頁查詢等方法。

具體參考: Db.java 。

更多關於Row 插入時的主鍵生成機制、以及Db 的事務管理等,請點擊 這裡 。

Entity 部分字段更新

相比市面上的其他框架,這部分的功能應該也算是MyBatis-Flex 的亮點之一。在BaseMapper 中,Mybatis-Flex 提供瞭如下的方法:


update(T entity,boolean ignoreNulls)

  • 第一個參數是entity 的對象。
  • 第二個參數是是否忽略null 值。

有些場景下,我們可能希望只更新幾個字段,而其中個別字段需要更新為null。此時需要用到 UpdateEntity 工具類,以下是示例程式碼:


Account account=UpdateEntity.of(Account.class);
account.setId(100);
account.setUserName(null);
account.setSex(1);

accountMapper.update(account,false);

以上的示例中,會把id 為100 這條數據中的user_name 字段更新為null,sex 字段更新為1,其他字段不會被更新。也就是說,通過 UpdateEntity 創建的對象,只會更新調用了setter 方法的字段,若不調用setter 方法,不管這個對象裡的屬性的值是什麼,都不會更新到數據庫。

其生成的sql 內容如下:


update tb_account
set user_name = ?, sex = ? where id = ? 
#params: null,1,100

多主鍵

Mybatis-Flex 多主鍵就是在Entity 類裡有多個 @Id 註解標識而已,比如:


@Table("tb_account")
public class Account {

    @Id(keyType = KeyType.Auto)
    private Long id;

    @Id(keyType = KeyType.Generator, value = "uuid")
    private String otherId;

    //getter setter
}

當我們保存數據的時候,Account 的id 主鍵為自增,而otherId 主鍵則通過uuid 生成。

自定義主鍵生成器

第1 步:編寫一個類,實現 IKeyGenerator 接口,例如:


public class UUIDKeyGenerator implements IKeyGenerator {

    @Override
    public Object generate(Object entity, String keyColumn) {
        return UUID.randomUUID().toString().replace("-", "");
    }
}

第2 步:註冊UUIDKeyGenerator


KeyGeneratorFactory.register("myUUID",new UUIDKeyGenerator());

第3 步:在Entity 裡使用”myUUID” 生成器:


@Table("tb_account")
public class Account {

    @Id(keyType = KeyType.Generator, value = "myUUID")
    private String otherId;

    //getter setter
}

使用數據庫Sequence 生成


@Table("tb_account")
public class Account {

    @Id(keyType = KeyType.Sequence, value = "select SEQ_USER_ID.nextval as id from dual")
    private Long id;

}

更多關於主鍵的配置,請點擊 這裡

更多文檔

You may also like

免費的WooCommerce產品過濾插件|動態的Ajax產品過濾器用於WooCommerce

WooCommerce WordPress電子商務網站的高級運輸教程

使用側邊欄過濾器使您的WooCommerce商店更好!

WooCommerce AI聊天機器人插件 – 使用AI立即回答產品問題!

WooCommerce多供應商產品拍賣插件 – 演練

使用WooCommerce(免費域 +託管)創建免費的電子商務網站|完整的分步指南

相关贴文:

  1. Mybatis-Flex首頁、文檔和下載- 優雅的Mybatis 增強框架- 科技資訊
  2. Mybatis-Flex 1.0-beta2 發布,一個優雅的Mybatis 增強框架- 科技資訊
  3. Furion v4.7.5 發布,首個支持(.NET7 正式版)適配框架
  4. Gitee 推薦| 一行程式碼獲取前端日誌log.js
  5. Visual Studio 2022 17.4 發布,首個支持Arm64 的GA 版本
  6. 谷歌為其開源芯片計劃免費提供芯片製造服務
  7. OAuthApp v2.2.10 更新| 前端發布工具- 科技資訊
  8. Ray 2.2 發布,機器學習框架- 科技資訊
Tags: Mybatis-Flex, 全新Logo,Mybatis-Flex v1.0 正式版發布

近期文章

  • 免費的WooCommerce產品過濾插件|動態的Ajax產品過濾器用於WooCommerce
  • WooCommerce WordPress電子商務網站的高級運輸教程
  • 使用側邊欄過濾器使您的WooCommerce商店更好!
  • WooCommerce AI聊天機器人插件 – 使用AI立即回答產品問題!
  • WooCommerce多供應商產品拍賣插件 – 演練
  • 使用WooCommerce(免費域 +託管)創建免費的電子商務網站|完整的分步指南
  • 如何使用WordPress,WooCommerce和Printful創建按需打印(POD)網站
  • 免費的WooCommerce自定義插件|自定義WooCommerce模板|購物者教程
  • 如何使用Hostinger(2025)🔥 -Hostinger WooCommerce教程構建電子商務網站!

標籤雲

Dropshipping ecommerce JavaScript Joomla OSCHINA博客 python REBELLION Shopify Shopify 商店設置 Shopify 直銷 Woocommerce WordPress 代發貨 刀塔2 和 商店 商業 喬姆拉 在 如何創建 Shopify 商店 如何在 如何建立 Shopify 商店 如何開始代出貨 年 店舖教學 店鋪化 店鋪培訓 教學 獲獎產品 直銷 Shopify 直銷教程 科技資訊 程式碼 網路業務 網路賺錢 臉書廣告 與 行銷 詳解 購物 跨平台 運輸船 適合初學者的 Shopify 教學課程 適合初學者的直銷 電子商務

Copyright 網絡設計教學 2025