• Xbatis:SpringBoot 数据管理框架


    Xbatis 是一个 SpringBoot 应用环境中使用的数据管理框架,它基于 MyBatis 实现,支持 MySQL,可以使用更加 Java 的方式实现业务逻辑中的 CRUD 操作。

    安装

    下载源码

    git clone https://github.com/njdi/durian.git
    

    编译源码

    cd durian/
    

    切换至最新版本(Tag),如:0.4,

    git checkout 0.4
    

    编译安装至本地 Maven 仓库:

    mvn clean package
    

    添加依赖

    SpringBoot 项目使用 Xbatis 时,需要在 Maven pom.xml 中添加:

    <dependency>
      <groupId>io.njdi</groupId>
      <artifactId>durian-xbatis</artifactId>
      <version>${version}</version>
    </dependency>
    

    ${version} 替换为具体的版本号,如:0.4。

    数据表

    数据表 mytable 包含 3 个字段:id、col1 和 col2,

    CREATE TABLE `mytable` (
      `id` int NOT NULL AUTO_INCREMENT,
      `col1` varchar(45) COLLATE utf8mb4_unicode_ci NOT NULL,
      `col2` varchar(45) COLLATE utf8mb4_unicode_ci NOT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
    
    

    其中,字段 id 是主键,且支持自增。

    Xbatis 中每一张数据表都要求必须包含一个整数类型的主键字段,名称为 id,且支持自增。

    数据源

    Xbatis 运行时需要使用 SpringBoot 提供的数据源(DataSource),需要在 application.yml 中添加:

    spring:
      application:
        name: sample
      datasource:
        url: jdbc:mysql://${host}:${port}/${db}?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true
        username: ${user}
        password: ${passwd}
        hikari:
          keepaliveTime: 30000
          maxLifetime: 600000
          maximumPoolSize: 30
    

    ${...} 替换为具体的数据库信息:

    • ${host}:MySQL 实例地址;
    • ${port}:MySQL 实例端口;
    • ${db}:数据库名称;
    • ${user}:用户名;
    • ${passwd}:密码;

    Xbatis

    Xbatis 是基于 MyBatis 实现的,运行时相关实例需要以 Bean 的形式注入到 Spring 容器,为保证 Spring 可以正常扫描且实例化这些 Bean,需要作如下配置:

    Main

    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.annotation.ComponentScan;
    
    @SpringBootApplication
    @ComponentScan({"io.njdi.durian.sample.xbatis", "io.njdi.durian.xbatis"})
    @MapperScan(basePackages = {"io.njdi.durian.xbatis.core"})
    public class Main {
      public static void main(String[] args) {
        SpringApplication.run(Main.class, args);
      }
    }
    

    Main 是 SpringBoot 应用的入口类,@ComponentScan 用于指定“去哪里”扫描 Xbatis 的 Bean,“io.njdi.durian.sample.xbatis” 是示例项目的 Bean,“io.njdi.durian.xbatis” 是 Xbatis 项目的 Bean;@MapperScan 用于指定“去哪里”扫描 MyBatis 的 Mapper。

    application.xml

    mybatis:
      mapper-locations: classpath:xbatis.xml
    

    mybatis.mapper-locations 用于指定“去哪里”加载 MyBatis 的配置文件。

    XbatisManager

    XbatisManager 是数据管理器实例,用以完成 CRUD 相关的具体操作,可以在 ServiceDao 层注入此实例:

    @Autowired
    private XbatisManager xbatisManager;
    

    Database/Table/Column

    Xbatis 中也有数据库(Database)、数据表(Table)和数据列(Column)的概念,它们是 业务逻辑 中的库/表/列,相较于 MySQL 中的 物理 库/表/列,它们拥有更多的业务属性。

    Column

    Column 用于定义 ,它对应着 MySQL 中的一列,包含以下属性:

    name

    列名称,指 业务逻辑 中列的名称;如果 业务逻辑 中列的名称与 MySQL 中对应列的名称不一致,则需要使用列别名(alias)指定。

    alias

    列别名,指 MySQL 中列的名称;仅列名称与列别名不一致时需要指定。

    type

    列类型,指 业务逻辑 中列的数据类型,支持数值和字符串类型,默认为字符串类型(String)。

    implicit

    列默认查询标识,查询数据表时,如果没有指定需要查询具体哪些列,会使用默认查询列替代,默认为 true。

    create

    列允许插入标识,指列是否支持插入,默认为 true。

    select

    列允许查询标识,指列是否支持查询,默认为 true。

    update

    列允许更新标识,指列是否支持更新,默认为 false。

    Column 实例支持通过 Builder 模式进行创建:

    Column id = Column.builder().name(COLUMN_MYTABLE_ID).type(Integer.class).create(false).build();
    Column colOne = Column.builder().name("colOne").alias("col1").build();
    Column colTwo = Column.builder().name("colTwo").alias("col2").build();
    

    其中,id 可使用 type() 指定类型为整数,使用 create() 指定不允许插入;colOne 和 colTwo 可使用 alias() 分别指定别名 col1 和 col2。

    Table

    Table 用于定义 ,它对应着 MySQL 中的一张表,包含以下属性:

    name

    表名称,指 业务逻辑 中表的名称;如果 业务逻辑 中表的名称与 MySQL 中对应表的名称不一致,则需要使用表别名(alias)指定。

    alias

    表别名,指 MySQL 中表的名称;仅表名称与表别名不一致时需要指定。

    columns

    列集合,指 某表的多个列(Column)。

    limit

    查询某表时,最多可以返回的记录数目,默认为整数最大值(Integer.MAX_VALUE),即不限制。

    create

    表允许插入标识,默认为 true。

    delete

    表允许删除标识,默认为 true。

    page

    表允许(分页)查询标识,默认为 true。

    update

    表允许更新标识,默认为 true。

    deleteMustHaveWhere

    表删除时,必须指定过滤条件标识,默认为 true。

    pageMustHaveWhere

    表查询时,必须指定过滤条件标识,默认为 true。

    updateMustHaveWhere

    表更新时,必须指定过滤条件标识,默认为 true。

    Table 实例支持通过 Builder 模式进行创建:

    Table myTable = Table.builder()
            .name("myTable")
            .alias("mytable")
            .column(id)
            .column(colOne)
            .column(colTwo)
            .build();
    

    使用 alias() 可指定表别名(注意 myTablemytable 的区别);使用 column() 可添加多个列。

    Database

    Database 用于定义 ,它对应着 MySQL 中的一个数据库,仅包含一个属性:

    tables

    表集合,指库的多张表(Table)。

    Database 实例支持通过 Builder 模式进行创建:

    Database database = Database.builder()
            .table(myTable)
            .build();
    

    使用 table() 可添加多张表。

    Database(库) 实例可以包含多个 Table(表) 实例;Table 实例可以包含多个 Column(列)实例。其中,Database 实例创建完成以后,需要以 Bean 的形式注入 Spring 容器:

    import io.njdi.durian.xbatis.model.schema.Column;
    import io.njdi.durian.xbatis.model.schema.Database;
    import io.njdi.durian.xbatis.model.schema.Table;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class DbConfigurer {
      public static final String TABLE_MYTABLE = "myTable";
    
      public static final String COLUMN_MYTABLE_ID = "id";
      public static final String COLUMN_MYTABLE_COL_ONE = "colOne";
      public static final String COLUMN_MYTABLE_COL_TWO = "colTwo";
    
      public Table createTable() {
        Column id = Column.builder().name(COLUMN_MYTABLE_ID).type(Integer.class).create(false).build();
        Column colOne = Column.builder().name(COLUMN_MYTABLE_COL_ONE).alias("col1").build();
        Column colTwo = Column.builder().name(COLUMN_MYTABLE_COL_TWO).alias("col2").build();
    
        return Table.builder()
                .name(TABLE_MYTABLE)
                .alias("mytable")
                .column(id)
                .column(colOne)
                .column(colTwo)
                .build();
      }
    
      @Bean
      public Database createDatabase() {
        Table myTable = createTable();
    
        return Database.builder()
                .table(myTable)
                .build();
      }
    }
    

    注意 @Configuration@Bean 两个注解的使用。其中,业务逻辑 中的表名和列名 均使用 公共静态常量(public/static/final) 进行声明,方便业务代码引用。

    Create/Creates

    Create 用于描述 插入 操作,每一个 Create 实例对应着一条 Insert 语句,如下:

    INSERT INTO mytable (col1, col2) VALUES('a', 'b')
    

    Insert 语句包含两部分重要内容:键值对和表名。键值对即列名和列值,如:

    col1 -> a
    col2 -> b
    

    Pair

    在 Xbatis 中键值对是使用 Pair 表示的,每一个 Pair 实例表示一组列名和列值;其中,列名使用属性 name 表示,列值使用属性 value 表示,如:

    Pair<String> colOne = Pair.<String>builder()
            .name(DbConfigurer.COLUMN_MYTABLE_COL_ONE)
            .value("a")
            .build();
    Pair<String> colTwo = Pair.<String>builder()
            .name(DbConfigurer.COLUMN_MYTABLE_COL_TWO)
            .value("b")
            .build();
    

    创建一个 Create 实例表示一条 Insert 语句:

    String table = DbConfigurer.TABLE_MYTABLE;
    
    Pair<String> colOne = Pair.<String>builder()
            .name(DbConfigurer.COLUMN_MYTABLE_COL_ONE)
            .value("a")
            .build();
    Pair<String> colTwo = Pair.<String>builder()
            .name(DbConfigurer.COLUMN_MYTABLE_COL_TWO)
            .value("b")
            .build();
    
    Create create = Create.builder()
            .pair(colOne)
            .pair(colTwo)
            .table(table)
            .build();
    

    创建 Create 实例时,使用了 DbConfigurer 中表名和列名的公共静态常量。

    id

    id 是 Create 中一个很重要的属性,它要求 MySQL 数据表中的主键字段名称为 id,且必须是自增的;使用 XbatisManager 执行插入操作后,可以获取已插入记录的主键值:

    int id = xbatisManager.create(create);
    log.info("id: {}", id);
    

    也可以通过 Create 实例获取主键值:

    log.info("id: {}", create.getId());
    

    Creates

    Creates 实例内部可以添加多个 Create 实例,用于表示多条记录的插入操作。

    Creates creates = Creates.builder()
            .create(create)
            .create(create2)
            .build();
    
    List<Integer> ids = xbatisManager.creates(creates);
    log.info("ids: {}", ids);
    

    Delete/Deletes

    Delete 用于描述 删除 操作,每一个 Delete 实例对应着一条 Delete 语句,如下:

    DELETE FROM mytable WHERE col1 = 'a'
    

    Delete 语句包含两部分重要内容:表名和过滤条件(可选)。

    Where

    Xbatis 中过滤条件使用 Where 表示,每一个 Where 实例表示一个过滤条件。Where 有四种实现:

    • Filter(基本过滤器)
    • OrFilter(逻辑或过滤器)
    • AndFilter(逻辑与过滤器)
    • NotFilter(逻辑非过滤器)

    Filter

    Filter 是基本过滤器的实现,它含有三个属性:

    name

    列名称。

    operator

    操作符,支持:EQ(=), NE(!=), GT(>), LT(<), GE(>=), LE(<=), BETWEEN(between ... and ...), LIKE(like), IN(in), NOT_IN(not in), IS_NULL(is null), IS_NOT_NULL(is not null)。

    values

    值列表,根据操作符的不同,可能是零个、一个或多个值。

    创建 Filter 实例:

    // col1 = 'a'
    Filter eq = Filter.builder()
            .name(DbConfigurer.COLUMN_MYTABLE_COL_ONE)
            .operator(Filter.Operator.EQ)
            .value("a")
            .build();
    
    // id between 1 and 10
    Filter between = Filter.builder()
            .name(DbConfigurer.COLUMN_MYTABLE_ID)
            .operator(Filter.Operator.BETWEEN)
            .value(1)
            .value(10)
            .build();
    
    // col2 is not null
    Filter isNotNull = Filter.builder()
            .name(DbConfigurer.COLUMN_MYTABLE_COL_TWO)
            .operator(Filter.Operator.IS_NOT_NULL)
            .build();
    

    Delete、Page 和 Update 实例均可以添加多个 Filter(Where) 实例,多个 Filter 之间的逻辑关系是 And(与)。

    OrFilter

    OrFilter 逻辑非过滤器,用于表示多个 Filter 之间的逻辑或(Or)关系。

    假设需要表示过滤:

    col1 = 'a' || col2 is not null
    

    使用 OrFilter:

    // col1 = 'a'
    Filter eq = Filter.builder()
            .name(DbConfigurer.COLUMN_MYTABLE_COL_ONE)
            .operator(Filter.Operator.EQ)
            .value("a")
            .build();
    
    // col2 is not null
    Filter isNotNull = Filter.builder()
            .name(DbConfigurer.COLUMN_MYTABLE_COL_TWO)
            .operator(Filter.Operator.IS_NOT_NULL)
            .build();
    
    // col1 = 'a' or col2 is not null
    OrFilter orFilter = OrFilter.builder()
            .filter(eq)
            .filter(isNotNull)
            .build();
    

    AndFilter

    AndFilter 逻辑与过滤器,用于表示多个 Filter 之间的逻辑与(And)关系,使用场景较少。

    NotFilter

    NotFilter 逻辑非过滤器,用于表示多个 Filter 之间的逻辑非(Not)关系,使用场景较少。

    使用 Where 创建 Delete 实例:

    String table = DbConfigurer.TABLE_MYTABLE;
    
    Filter colOne = Filter.builder()
            .name(DbConfigurer.COLUMN_MYTABLE_COL_ONE)
            .operator(Filter.Operator.EQ)
            .value("a")
            .build();
    
    Delete delete = Delete.builder()
            .table(table)
            .where(colOne)
            .build();
    

    可以使用 Delete where() 添加多个 Where 实例,它们之间的逻辑关系是与(And)。

    执行删除操作:

    int rows = xbatisManager.delete(delete);
    log.info("rows: {}", rows);
    

    XbatisManager delete() 会返回执行删除操作后所影响的记录行数,也可以使用 Deletes 执行多个删除操作。

    Page

    Page 用于描述 查询 操作,每一个 Page 实例对应着一条 Select 语句,它是 Xbatis 中最复杂的结构,包含若干组成部分:

    • Field(查询字段)
    • Where(过滤)
    • Group(分组)
    • Having(分组过滤)
    • Order(排序)
    • limit/offset(分页)

    Field

    Field 用于描述 查询字段 部分:

    SELECT
        
        select_expr [, select_expr] ...
    FROM
        table
    

    select_expr 就是查询字段,每一个 Field 实例对应着一个 查询字段,它包含两个属性:

    name

    列名称。

    alias

    列别名,如果需要为查询的列起一个其它的名称,可以使用列别名指定。

    创建 Field 实例:

    Field field = Field.builder()
            .name(DbConfigurer.COLUMN_MYTABLE_COL_ONE)
            .alias("mycol")
            .build();
    

    翻译成 SQL 片段:

    SELECT
        col1 AS mycol
    FROM
        table
    

    Where

    SELECT
        select_expr [, select_expr] ...
    FROM
        table
    WHERE
        where_condition
    

    详细内容参考 Delete Where。

    Group

    列名称集合,每一个列名称表示一个分组字段,直接使用字符串表示。

    SELECT
        select_expr [, select_expr] ...
    FROM
        table
    WHERE
        where_condition
    GROUP BY
        col_name [, col_name] ...
    

    Having

    SELECT
        select_expr [, select_expr] ...
    FROM
        table
    WHERE
        where_condition
    GROUP BY
        col_name [, col_name] ...
    HAVING
        where_condition
    

    详细内容参考 Delete Where。

    Order

    Order 用于描述 排序字段 部分:

    SELECT
        select_expr [, select_expr] ...
    FROM
        table
    WHERE
        where_condition
    GROUP BY
        col_name [, col_name] ...
    HAVING
        where_condition
    ORDER BY order_expr [, order_expr] ...
    

    order_expr 就是排序字段,每一个 Order 实例对应着一个 排序字段,它包含两个属性:

    name

    列名称。

    sort

    排序,升序(ASC)或降序(DESC)。

    创建 Order 实例:

    Order order = Order.builder()
            .name(DbConfigurer.COLUMN_MYTABLE_COL_ONE)
            .sort(Order.Sort.DESC)
            .build();
    

    翻译成 SQL 片段:

    ORDER BY col1 DESC
    

    limit/offset

    limit 用于限制查询返回的记录行数,offset 用于指定记录偏移量,两者结合可实现分页。

    SELECT
        select_expr [, select_expr] ...
    FROM
        table
    WHERE
        where_condition
    GROUP BY
        col_name [, col_name] ...
    HAVING
        where_condition
    ORDER BY order_expr [, order_expr] ...
    LIMIT limit 
    OFFSET offset
    

    创建 Page 实例:

    Page page = Page.builder()
            .field(...)
            .table(table)
            .where(...)
            .group(...)
            .having(...)
            .order(...)
            .limit(...)
            .offset(...)
            .build();
    

    其中,field()、where()、group()、having()、order() 均可以使用多次。

    执行查询操作:

    List<Map<String, Object>> rows = xbatisManager.page(page);
    log.info("rows: {}", rows);
    

    XbatisManager page() 会返回一个记录集合,使用 List 表示;每一个记录使用一个 Map 表示,Key(String)代表列名称,Value(Object)代表列值。

    XbatisManager page() 有一个重载方法,可以直接以 对象集合 的形式返回查询结果:

    public class MyRow {
      private Integer id;
      private String colOne;
      private String colTwo;
    }
    
    List<MyRow> rows = xbatisManager.page(page, MyRow.class);
    log.info("rows: {}", rows);
    

    每一个 MyRow 实例表示一行记录。注意,MyRow 属性名称及类型必须与列名称及类型一一对应。

    id/ids

    使用 ID 查询记录是很常见的需求,Xbatis 直接支持这样的查询请求。ID 可以有两种解读:

    • MySQL 数据表记录中的自增 id
    • 业务逻辑中的唯一记录标识

    对于第一种情况:

    String table = DbConfigurer.TABLE_MYTABLE;
    
    int id = 106;
    
    MyRow myRow = xbatisManager.id(table, id, MyRow.class);
    log.info("id: {}", myRow);
    

    直接使用 id 值查询对应的记录。

    对于第二种情况:

    String table = DbConfigurer.TABLE_MYTABLE;
    
    String name = "id";
    Integer value = 106;
    
    MyRow myRow = xbatisManager.id(table, name, value, MyRow.class);
    log.info("id: {}", myRow);
    

    需要特别指定唯一记录标识列的名称 name。

    此外,id() 也支持返回 Map 类型的记录。

    ids() 可以查询 ID 集合(多个ID)的记录列表。如果 ID 集合中存在 重复 的 ID,返回的记录列表也会包含 重复 的记录。

    Update/Updates

    Update 用于描述 更新 操作,每一个 Update 实例对应着一条 Update 语句,如下:

    UPDATE 
        mytable 
    SET 
        col2 = 'b'
    WHERE
        col1 = 'a'
    

    Update 语句包含三部分重要内容:表名,键值对(Pair)和过滤条件(Where);其中,Pair 请参考 Create Pair,Where 请参考 Delete Where。

    创建 Update 实例:

    String table = DbConfigurer.TABLE_MYTABLE;
    
    Filter filter = Filter.builder()
            .name(DbConfigurer.COLUMN_MYTABLE_COL_ONE)
            .operator(Filter.Operator.EQ)
            .value("a")
            .build();
    
    Pair<String> pair = Pair.<String>builder()
            .name(DbConfigurer.COLUMN_MYTABLE_COL_TWO)
            .value("c")
            .build();
    
    Update update = Update.builder()
            .table(table)
            .pair(pair)
            .where(filter)
            .build();
    

    执行更新操作:

    int rows = xbatisManager.update(update);
    log.info("rows: {}", rows);
    

    XbatisManager update() 会返回执行更新操作后所影响的记录行数,也可以使用 Updates 执行多个删除操作。

    自定义列名称

    一般情况下,Field.nameFilter.nameOrder.name 只能使用已经定义的列名称 Column.name。如果需要使用自定义的列名称,则需要通过 expr 属性额外指定。

    以 Field 为例,假设需要查询列 colOne 大写之后的值:

    Field field = Field.builder()
            .name("UPPER(col1)")
            .alias("colOne")
            .expr(true)
            .build();
    

    注意,使用自定义列名称时,只能引用 MySQL 数据表中的列名,如:col1。

    示例

  • 相关阅读:
    python函数
    文件操作
    python列表,元组,字典,集合简介
    python字符串(str)
    python数字类型 or 进制转换
    流程控制
    Python入门
    Python垃圾回收机制
    python简介&下载&安装
    DAY11
  • 原文地址:https://www.cnblogs.com/yurunmiao/p/15818946.html
Copyright © 2020-2023  润新知