Mybatis-Plus不支持联合主键(复合主键)怎么办?试试Mybatis-Tiny

Mybatis-Tiny是什么

Mybatis-Tiny是一个基于Mybatis框架的一层极简的扩展,它旨在使用DSL的方式对单表进行CRUD操作,类似于Mybatis-Plus框架,但它绝不是重复造轮子!区别于别的类似框架(如Mybatis-Plus、Fluent-Mybatis等)的实现方式,它采用一种逆向曲线救国的实现方式,通过较少的代码,极简的扩展实现了类似于他们大多数的功能,完全满足日常开发中对单表的各种CRUD操作。

项目地址:https://github.com/penggle/my...

联合主键使用案例

  • 引入并使用Mybatis-Tiny

    (以下基于SpringBoot方式使用Mybatis)

    • 引入依赖
      
          io.github.penggle
          mybatis-tiny-core
          
          3.5
      
    • 相关配置

      引入相关Maven依赖后在SpringBoot启动类上使用注解@EnableMybatisTiny即可,例如:

      import com.penglecode.codeforce.mybatistiny.EnableMybatisTiny;
      import com.penglecode.codeforce.mybatistiny.examples.BasePackage;
      import org.springframework.boot.autoconfigure.SpringBootApplication;
      
      @EnableMybatisTiny
      @SpringBootApplication(scanBasePackageClasses=BasePackage.class)
      public class MybatisTinyExampleApplication {
      
          public static void main(String[] args) {
              SpringApplication.run(MybatisTinyExampleApplication.class, args);
          }
      
      }

      mybatis-spring-boot-starterDataSource的配置照旧就好了,application.yml例如:

      #SpringBoot应用的名称
      spring:
          application:
              name: mybatis-tiny-examples-springboot
          #Hikari 连接池配置
          datasource:
              hikari:
                  #连接池名字
                  pool-name: defaultHikariCP
                  #最小空闲连接数量
                  minimum-idle: 5
                  #空闲连接存活最大时间,默认600000(10分钟)
                  idle-timeout: 180000
                  #连接池最大连接数,默认是10
                  maximum-pool-size: 10
                  #池中连接的默认自动提交行为,默认值true
                  auto-commit: true
                  #池中连接的最长生命周期,0表示无限生命周期,默认1800000(30分钟)
                  max-lifetime: 1800000
                  #等待来自池的连接的最大毫秒数,默认30000(30秒)
                  connection-timeout: 30000
                  #连接测试语句
                  connection-test-query: SELECT 1
              username: root
              password: 123456
              url: jdbc:mysql://127.0.0.1:3306/examples?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&serverTimezone=GMT%2B8&useSSL=false&rewriteBatchedStatements=true&useCursorFetch=true
      
      #Mybatis-SpringBoot配置
      mybatis:
          config-location: classpath:config/mybatis/mybatis-config.xml
          mapper-locations: classpath*:com/penglecode/codeforce/mybatistiny/examples/**/*Mapper.xml
          type-aliases-package: com.penglecode.codeforce.mybatistiny.examples
          type-aliases-super-type: com.penglecode.codeforce.common.domain.DomainObject
  • 基于Mybatis-Tiny的联合主键使用案例

    • 基于注解的实体对象定义:
      package com.penglecode.samples.order.domain.model;
      
      import com.penglecode.codeforce.common.domain.EntityObject;
      import com.penglecode.codeforce.mybatistiny.annotations.GenerationType;
      import com.penglecode.codeforce.mybatistiny.annotations.Id;
      import com.penglecode.codeforce.mybatistiny.annotations.Table;
      import com.penglecode.samples.order.domain.enums.OrderStatusEnum;
      
      /**
       * 主订单信息
       */
      @Table("t_order")
      public class Order implements EntityObject {
      
          /** 订单ID */
          @Id(strategy=GenerationType.NONE)
          private Long orderId;
      
          /** 客户ID */
          private Long customerId;
      
          /** 总金额(单位分) */
          private Long totalAmount;
      
          /** 总运费(单位分) */
          private Long totalFreight;
      
          /** 商户ID */
          private Long shopId;
      
          /** 下单时间 */
          private String orderTime;
      
          /** 订单状态 */
          private OrderStatusEnum orderStatus;
      
          /** 订单备注 */
          private String remark;
      
          private String createTime;
      
          private String updateTime;
      
          //getter/setter省略
      
          @Override
          public Long identity() {
              return orderId;
          }
      
      }
      package com.penglecode.samples.order.domain.model;
      
      import com.penglecode.codeforce.common.domain.EntityObject;
      import com.penglecode.codeforce.common.domain.ID;
      import com.penglecode.codeforce.mybatistiny.annotations.GenerationType;
      import com.penglecode.codeforce.mybatistiny.annotations.Id;
      import com.penglecode.codeforce.mybatistiny.annotations.Table;
      import com.penglecode.samples.order.domain.enums.OrderStatusEnum;
      
      /**
       * 订单明细
       */
      @Table("t_order_line")
      public class OrderLine implements EntityObject {
      
          /** 订单ID */
          @Id(strategy= GenerationType.NONE)
          private Long orderId;
      
          /** 商品ID */
          @Id(strategy=GenerationType.NONE)
          private Long productId;
      
          /** 商品名称 */
          private String productName;
      
          /** 商品详情页URL */
          private String productUrl;
      
          /** 商品单价(单位分) */
          private Long unitPrice;
      
          /** 购买数量 */
          private Integer quantity;
      
          /** 运费 */
          private Long freight;
      
          /** 小计(单位分) */
          private Long subTotalAmount;
      
          /** 订单状态 */
          private OrderStatusEnum orderStatus;
      
          /** 下单时间 */
          private String orderTime;
      
          private String createTime;
      
          private String updateTime;
      
          //getter/setter省略
      
          @Override
          public ID identity() {
              //联合主键
              return new ID().addKey("orderId", orderId).addKey("productId", productId);
          }
      
      }
      
      /**
       * 订单状态
       */
      public enum OrderStatusEnum {
      
          WAIT_PAY,
      
          PAIED,
      
          REFUND,
      
          CLOSED
      
      }
    • 实体Mapper接口定义:
      @Mapper
      public interface OrderMapper extends BaseEntityMapper {
      
      }
      
      @Mapper
      public interface OrderLineMapper extends BaseEntityMapper {
      
      }
    • CRUD使用示例:
      @SpringBootTest(classes=SamplesApplication.class)
      public class OrderMapperTest {
      
          @Autowired
          private OrderMapper orderMapper;
      
          @Autowired
          private OrderLineMapper orderLineMapper;
      
          @Autowired
          private DataSourceTransactionManager dataSourceTransactionManager;
      
          protected  void doInTransaction(Supplier executor) {
              new TransactionTemplate(dataSourceTransactionManager).execute(status -> executor.get());
          }
      
          @Test
          public void createOrder() {
              doInTransaction(this::doCreateOrder);
          }
      
          protected Object doCreateOrder() {
              String nowTime = DateTimeUtils.formatNow();
              //Long orderId = System.currentTimeMillis();
              Long orderId = 1651560129068L;
      
              List orderLines = new ArrayList<>();
              OrderLine orderLine1 = new OrderLine();
              orderLine1.setProductId(100026667880L);
              orderLine1.setProductName("Apple iPhone 13 (A2634) 128GB 午夜色 支持移动联通电信5G 双卡双待手机");
              orderLine1.setProductUrl("https://item.jd.com/100026667880.html");
              orderLine1.setUnitPrice(599900L);
              orderLine1.setQuantity(1);
              orderLine1.setFreight(0L);
              orderLines.add(orderLine1);
      
              OrderLine orderLine2 = new OrderLine();
              orderLine2.setProductId(100034710000L);
              orderLine2.setProductName("Apple iPad Air5 10.9英寸平板电脑 2022年款(64G WLAN版/M1芯片Liquid视网膜屏 MME23CH/A) 紫色");
              orderLine2.setProductUrl("https://item.jd.com/100034710000.html");
              orderLine2.setUnitPrice(439900L);
              orderLine2.setQuantity(1);
              orderLine2.setFreight(0L);
              orderLines.add(orderLine2);
      
              Order order = new Order();
              order.setOrderId(orderId);
              order.setOrderTime(nowTime);
              order.setCustomerId(123L);
              order.setShopId(1000000127L);
              order.setTotalAmount(0L);
              order.setTotalFreight(0L);
              order.setOrderStatus(OrderStatusEnum.WAIT_PAY);
              order.setCreateTime(nowTime);
              order.setUpdateTime(nowTime);
      
              for(OrderLine orderLine : orderLines) {
                  orderLine.setOrderId(orderId);
                  orderLine.setSubTotalAmount(orderLine.getUnitPrice() * orderLine.getQuantity());
                  order.setTotalFreight(order.getTotalFreight() + orderLine.getFreight());
                  order.setTotalAmount(order.getTotalAmount() + orderLine.getSubTotalAmount());
                  orderLine.setOrderStatus(order.getOrderStatus());
                  orderLine.setOrderTime(nowTime);
                  orderLine.setCreateTime(nowTime);
                  orderLine.setUpdateTime(nowTime);
              }
      
              //insert主订单信息
              orderMapper.insert(order);
              //批量insert订单明细
              orderLineMapper.batchUpdate(orderLines, orderLine -> orderLineMapper.insert(orderLine));
              return orderId;
          }
      
          @Test
          public void updateOrder() {
              doInTransaction(this::doUpdateOrder);
          }
      
          protected Object doUpdateOrder() {
              Long orderId = 1651560129068L;
              String nowTime = DateTimeUtils.formatNow();
              OrderStatusEnum targetOrderStatus = OrderStatusEnum.PAIED;
      
              Map orderUpdateColumns = MapLambdaBuilder.ofEmpty()
                      .withOverride(Order::getOrderStatus, targetOrderStatus)
                      .withOverride(Order::getRemark, "已付款,请发顺丰快递!")
                      .withOverride(Order::getUpdateTime, nowTime)
                      .build();
              orderMapper.updateById(orderId, orderUpdateColumns); //更新主订单
      
              Map orderLineUpdateColums = MapLambdaBuilder.ofEmpty()
                      .withOverride(OrderLine::getOrderStatus, targetOrderStatus)
                      .withOverride(OrderLine::getUpdateTime, nowTime)
                      .build();
              QueryCriteria orderLineUpdateCriteria = LambdaQueryCriteria.ofSupplier(OrderLine::new)
                      .eq(OrderLine::getOrderId, orderId);
              orderLineMapper.updateByCriteria(orderLineUpdateCriteria, orderLineUpdateColums); //更新子订单
              return orderId;
          }
      
          @Test
          public void getOrderById() {
              Long orderId = 1651560129068L;
              Order order = orderMapper.selectById(orderId); //根据单个ID查询
              System.out.println(JsonUtils.object2Json(order));
      
              //联合主键
              List orderLineIds = new ArrayList<>();
              orderLineIds.add(new ID().addKey(OrderLine::getOrderId, orderId).addKey(OrderLine::getProductId, 100026667880L));
              orderLineIds.add(new ID().addKey(OrderLine::getOrderId, orderId).addKey(OrderLine::getProductId, 100034710000L));
              List orderLines = orderLineMapper.selectListByIds(orderLineIds); //根据多个ID查询
              orderLines.forEach(orderLine -> System.out.println(JsonUtils.object2Json(orderLine)));
          }
      
      }

      打印SQL:

      #createOrder()
      
       - ==>  Preparing: INSERT INTO t_order( order_id, customer_id, total_amount, total_freight, shop_id, order_time, order_status, remark, create_time, update_time ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )
       - ==> Parameters: 1651560129068(Long), 123(Long), 1039800(Long), 0(Long), 1000000127(Long), 2022-05-03 17:29:30(String), WAIT_PAY(String), null, 2022-05-03 17:29:30(String), 2022-05-03 17:29:30(String)
       - <==    Updates: 1
       
       - ==>  Preparing: INSERT INTO t_order_line( order_id, product_id, product_name, product_url, unit_price, quantity, freight, sub_total_amount, order_status, order_time, create_time, update_time ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )
       - ==> Parameters: 1651560129068(Long), 100026667880(Long), Apple iPhone 13 (A2634) 128GB 午夜色 支持移动联通电信5G 双卡双待手机(String), https://item.jd.com/100026667880.html(String), 599900(Long), 1(Integer), 0(Long), 599900(Long), WAIT_PAY(String), 2022-05-03 17:29:30(String), 2022-05-03 17:29:30(String), 2022-05-03 17:29:30(String)
       - ==> Parameters: 1651560129068(Long), 100034710000(Long), Apple iPad Air5 10.9英寸平板电脑 2022年款(64G WLAN版/M1芯片Liquid视网膜屏 MME23CH/A) 紫色(String), https://item.jd.com/100034710000.html(String), 439900(Long), 1(Integer), 0(Long), 439900(Long), WAIT_PAY(String), 2022-05-03 17:29:30(String), 2022-05-03 17:29:30(String), 2022-05-03 17:29:30(String)
      
      
      #updateOrder()
      
       - ==>  Preparing: UPDATE t_order SET order_status = ?, remark = ?, update_time = ? WHERE order_id = ?
       - ==> Parameters: PAIED(String), 已付款,请发顺丰快递!(String), 2022-05-03 17:31:05(String), 1651560129068(Long)
       - <==    Updates: 1
       - ==>  Preparing: UPDATE t_order_line SET order_status = ?, update_time = ? WHERE order_id = ?
       - ==> Parameters: PAIED(String), 2022-05-03 17:31:05(String), 1651560129068(Long)
       - <==    Updates: 2
       
      #getOrderById()
      
       - ==>  Preparing: SELECT order_id AS orderId, customer_id AS customerId, total_amount AS totalAmount, total_freight AS totalFreight, shop_id AS shopId, order_time AS orderTime, order_status AS orderStatus, remark AS remark, create_time AS createTime, update_time AS updateTime FROM t_order WHERE order_id = ?
       - ==> Parameters: 1651560129068(Long)
       - <==      Total: 1
       - ==>  Preparing: SELECT order_id AS orderId, product_id AS productId, product_name AS productName, product_url AS productUrl, unit_price AS unitPrice, quantity AS quantity, freight AS freight, sub_total_amount AS subTotalAmount, order_status AS orderStatus, order_time AS orderTime, create_time AS createTime, update_time AS updateTime FROM t_order_line WHERE (order_id = ? AND product_id = ?) OR (order_id = ? AND product_id = ?)
       - ==> Parameters: 1651560129068(Long), 100026667880(Long), 1651560129068(Long), 100034710000(Long)
       - <==      Total: 2

你可能感兴趣的:(Mybatis-Plus不支持联合主键(复合主键)怎么办?试试Mybatis-Tiny)