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

Mybatis-Tiny是什么 【Mybatis-Plus不支持联合主键(复合主键)怎么办(试试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-core3.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

  • 更多示例请见:https://github.com/penggle/my...

    推荐阅读