liuanxin / table-column-example

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

table-column-example

假定有如下这样的表

DROP TABLE IF EXISTS `t_order`;
CREATE TABLE `t_order` (
  `id` bigint unsigned NOT NULL AUTO_INCREMENT,
  `order_no` varchar(32) NOT NULL COMMENT '订单号',
  `order_status` int unsigned NOT NULL DEFAULT '0' COMMENT '订单状态(0.用户已创建待支付, 1.用户已支付待商户发货, 2.商户已发货待用户签收, 3.用户已签收待确认完结, 4.已完结)',
  `amount` decimal(20,2) unsigned NOT NULL DEFAULT '0.00' COMMENT '订单金额',
  `desc` varchar(32) NOT NULL DEFAULT '' COMMENT '备注',
  `create_time` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '创建时间',
  `update_time` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) COMMENT '更新时间',
  `deleted` int unsigned NOT NULL DEFAULT '0' COMMENT '0.未删除, 非 0.已删除',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_order_no` (`order_no`,`deleted`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='订单';

INSERT INTO `t_order` (`order_no`, `order_status`, `amount`, `desc`) VALUES
('1-2-221010-00001', 1, 9258.00, '请尽快发货'), ('1-2-221010-00002', 2, 6900.00, '');


DROP TABLE IF EXISTS `t_order_address`;
CREATE TABLE `t_order_address` (
  `id` bigint unsigned NOT NULL AUTO_INCREMENT,
  `order_no` varchar(32) NOT NULL DEFAULT '' COMMENT '订单号',
  `contact` varchar(16) NOT NULL DEFAULT '' COMMENT '联系人',
  `phone` varchar(16) NOT NULL DEFAULT '' COMMENT '联系电话',
  `address` varchar(128) NOT NULL DEFAULT '' COMMENT '联系人地址',
  `create_time` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '创建时间',
  `update_time` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) COMMENT '更新时间',
  `deleted` bigint unsigned NOT NULL DEFAULT '0' COMMENT '0.未删除, 非 0.已删除',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_order_no` (`order_no`,`deleted`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='订单地址';

INSERT INTO `t_order_address` (`order_no`, `contact`, `phone`, `address`) VALUES
('1-2-221010-00001', '张三', '13012345678', '北京市朝阳区'), ('1-2-221010-00002', '李四', '13122223333', '广东省广州市白云区');


DROP TABLE IF EXISTS `t_order_item`;
CREATE TABLE `t_order_item` (
  `id` bigint unsigned NOT NULL AUTO_INCREMENT,
  `order_no` varchar(32) NOT NULL DEFAULT '' COMMENT '订单号',
  `product_name` varchar(32) NOT NULL DEFAULT '' COMMENT '商品名',
  `price` decimal(20,2) unsigned NOT NULL DEFAULT '0.00' COMMENT '商品价格',
  `number` int unsigned NOT NULL DEFAULT '0' COMMENT '商品数量',
  PRIMARY KEY (`id`),
  KEY `idx_order_no` (`order_no`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='订单项(商品)';

INSERT INTO `t_order_item` (`order_no`, `product_name`, `price`, `number`) VALUES
('1-2-221010-00001', 'iPhone 14 Pro', 8999, 1), ('1-2-221010-00001', '女款外套', 129.5, 2),
('1-2-221010-00002', 'Samsung', 6999.00, 1);


DROP TABLE IF EXISTS `t_order_log`;
CREATE TABLE `t_order_log` (
  `id` bigint unsigned NOT NULL AUTO_INCREMENT,
  `order_no` varchar(32) NOT NULL DEFAULT '' COMMENT '订单号',
  `operator` varchar(32) NOT NULL DEFAULT '' COMMENT '操作人',
  `message` text COMMENT '操作内容',
  `time` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '创建时间',
  `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '0.未删除, 1.已删除',
  PRIMARY KEY (`id`),
  KEY `idx_order_no` (`order_no`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='订单日志';

INSERT INTO `t_order_log` (`order_no`, `operator`, `message`, `time`) VALUES
('1-2-221010-00001', '张三', '创建订单', '2022-10-01 11:12:13'),
('1-2-221010-00001', '张三', '支付成功', '2022-10-01 12:13:14'),
('1-2-221010-00002', '李四', '创建订单', '2022-10-01 12:15:14'),
('1-2-221010-00002', '李四', '支付成功', '2022-10-01 12:16:14'),
('1-2-221010-00002', '李四', '已发货, 待用户收货', '2022-10-01 12:17:14');

配置如下

@Configuration
public class TableColumnConfig {

    @Bean
    public List<TableColumnRelation> tableRelationList() {
        // 表与表之间的关联关系
        return List.of(
                // 订单 跟 订单地址 一对一, 用 订单号 字段关联
                new TableColumnRelation("t_order", "order_no", TableRelationType.ONE_TO_ONE, "t_order_address", "order_no"),
                // 订单 跟 订单项 一对多, 用 订单号 字段关联
                new TableColumnRelation("t_order", "order_no", TableRelationType.ONE_TO_MANY, "t_order_item", "order_no"),
                // 订单 跟 订单日志 一对多, 用 订单号 字段关联
                new TableColumnRelation("t_order", "order_no", TableRelationType.ONE_TO_MANY, "t_order_log", "order_no")
        );
    }

    // 查询别名
    @Bean("queryAliasMap")
    public Map<String, ReqAlias> queryAlias() {
        return Map.of(
                // 用这个查询别名时, 只有订单表(所有字段)
                "all-order", new ReqAlias("Order"),
                "order-address-item-log", orderAddressItemLogAlias()
        );
    }

    private ReqAlias orderAddressItemLogAlias() {
        // 指定 订单表 的字段, 指定 订单地址表 订单项表 订单日志表 的字段, 查询 Order 时 distinct, 并指定查询时多张表之间的关联方式
        ReqResult result = new ReqResult(List.of(
                "orderNo", "orderStatus", "amount", "desc", "createTime",
                Map.of("address", Map.of("table", "OrderAddress", "columns", List.of("contact", "phone", "address"))),
                Map.of("items", Map.of("table", "OrderItem", "columns", List.of("productName", "price", "number"))),
                Map.of("logs", Map.of("table", "OrderLog", "columns", List.of("operator", "message", "time")))
        ), true);
        List<List<String>> relationList = List.of(List.of("Order", "inner", "OrderAddress"), List.of("Order", "left", "OrderItem"));
        return new ReqAlias("Order", result, relationList);
    }
}

web 接口如下

@RestController
public class TableColumnController {

    private final TableColumnTemplate tableColumnTemplate;
    public TableColumnController(TableColumnTemplate tableColumnTemplate) {
        this.tableColumnTemplate = tableColumnTemplate;
    }

    @GetMapping("/table-column")
    public List<QueryInfo> info(String tables) {
        return tableColumnTemplate.info(tables);
    }

    @PostMapping("/table-column")
    public Object query(@RequestBody ReqInfo req) {
        return tableColumnTemplate.dynamicQuery(req);
    }
}

请求 GET /table-column 会返回表字段及表关联关系, 如果配置 query.has-not-return-info = true 则此接口返回空

下面是 POST /table-column 时请求参数以及最终执行的 sql, 最终会以请求参数中的 result 以及 返回结果 的示例

请求参数

{
  "table" : "Order",
  "param" : {
    "page": [1,5]
  }
}

执行 sql

SELECT COUNT(*) FROM t_order WHERE deleted = 0


SELECT .. FROM t_order WHERE deleted = 0 LIMIT 5

请求参数(默认情况下, param 必须要有 query 或 page 才能进行查询, 可以用 query.not-required-condition-or-page = true 去掉此限制

{
  "table" : "Order",
  "param" : {
    "query": {
      "conditions": [
        [ "id", "gt", 0 ]
      ]
    }
  }
}

执行 sql

SELECT .. FROM t_order WHERE ( id > 0 ) AND deleted = 0

请求参数

{
  "table": "Order",
  "param": {
    "query": {
      "conditions": [
        [ "id", "gt", 0 ]
      ]
    }
  },
  "result": {
    "columns": [
      "orderNo", "orderStatus", "amount", "desc", "createTime",
      {
        "address": {
          "table": "OrderAddress",
          "columns": [  "contact",   "address" ]
        }
      },
      {
        "items": {
          "table": "OrderItem",
          "columns": [ "productName", "price",  "number" ]
        }
      },
      {
        "logs": {
          "table": "OrderLog",
          "columns": [ "operator", "message", "time" ]
        }
      }
    ]
  }
}

会依次执行以下 sql 并将数据组装返回(关联表会批量查询避免 n+1, 数量过多会分批查询, 单次数量由 query.max-list-count 控制)

SELECT .. FROM t_order WHERE ( id > 0 ) AND deleted = 0


SELECT .. FROM t_order_address WHERE ( order_no IN ('1-2-221010-00001', '1-2-221010-00002') )
AND deleted = 0


SELECT .. FROM t_order_item WHERE order_no IN ('1-2-221010-00001', '1-2-221010-00002')


SELECT .. FROM t_order_log WHERE ( order_no IN ('1-2-221010-00001', '1-2-221010-00002') )
AND deleted = 0

请求参数

{
  "table": "Order",
  "param": {
    "query": {
      "conditions": [
        [ "id", "gt", 0 ],
        [ "OrderItem.productName", "ne", "" ],
        [ "OrderAddress.contact", "ne", "" ]
      ]
    },
    "sort": { "createTime": "desc" },
    "relation": [ [ "Order", "inner", "OrderItem" ],  [ "Order", "inner", "OrderAddress" ] ],
    "page": [ 1, 5 ]
  },
  "result": {
    "columns": [
      "orderNo", "orderStatus", "amount", "desc", "createTime",
      {
        "address": {
          "table": "OrderAddress",
          "columns": [  "contact",   "address" ]
        }
      },
      {
        "items": {
          "table": "OrderItem",
          "columns": [ "productName", "price",  "number" ]
        }
      },
      {
        "logs": {
          "table": "OrderLog",
          "columns": [ "operator", "message", "time" ]
        }
      }
    ],
    "distinct": true
  }
}

param 下的 query sort page 是动态外, 上面的 table result param.relation 部分可以由 queryAlias 去定义, 如上面定义的 order-address-item-log 别名.

下面的入参可以达到跟上面等同的查询效果, 这样一来, 后端只需要定义好 queryAlias 就可以了

{
  "alias": "order-address-item-log",
  "param": {
    "query": {
      "conditions": [
        [ "id", "gt", 0 ],
        [ "OrderItem.productName", "ne", "" ],
        [ "OrderAddress.contact", "ne", "" ]
      ]
    },
    "sort": { "createTime": "desc" },
    "page": [ 1, 5 ]
  }
}

上面的查询入参会依次执行以下 sql 并将数据组装返回(关联表会批量查询避免 n+1, 数量过多会分批查询, 单次数量由 query.max-list-count 控制)

SELECT COUNT(DISTINCT `Order`.id)
FROM t_order AS `Order`
INNER JOIN t_order_item AS OrderItem ON OrderItem.order_no = `Order`.order_no
INNER JOIN t_order_address AS OrderAddress ON OrderAddress.order_no = `Order`.order_no
WHERE ( `Order`.id > 0 AND OrderItem.product_name <> '' AND OrderAddress.contact <> '' )
AND `Order`.deleted = 0 AND OrderAddress.deleted = 0


SELECT DISTINCT `Order`.order_no AS orderNo, ..
FROM t_order AS `Order`
INNER JOIN t_order_item AS OrderItem ON OrderItem.order_no = `Order`.order_no
INNER JOIN t_order_address AS OrderAddress ON OrderAddress.order_no = `Order`.order_no
WHERE ( `Order`.id > 0 AND OrderItem.product_name <> '' AND OrderAddress.contact <> '' )
AND `Order`.deleted = 0 AND OrderAddress.deleted = 0
ORDER BY `Order`.create_time DESC
LIMIT 5


SELECT .. FROM t_order_address
WHERE ( order_no IN ('1-2-221010-00001', '1-2-221010-00002') ) AND deleted = 0


SELECT .. FROM t_order_item WHERE order_no IN ('1-2-221010-00001', '1-2-221010-00002')


SELECT .. FROM t_order_log WHERE ( order_no IN ('1-2-221010-00001', '1-2-221010-00002') )
AND deleted = 0

About


Languages

Language:Java 100.0%