美文网首页J2ee
Mybatis-Plus不支持联合主键(复合主键)怎么办?试试M

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

作者: Pengle | 来源:发表于2022-05-03 17:34 被阅读0次

    Mybatis-Tiny是什么

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

    项目地址:https://github.com/penggle/mybatis-tiny

    联合主键使用案例

    • 引入并使用Mybatis-Tiny

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

      • 引入依赖
        <dependency>
            <groupId>io.github.penggle</groupId>
            <artifactId>mybatis-tiny-core</artifactId>
            <!-- 版本说明:3.5指的是基于Mybatis 3.5.x版本的意思 -->
            <version>3.5</version>
        </dependency>
        
      • 相关配置

        引入相关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<Order> {
        
        }
        
        @Mapper
        public interface OrderLineMapper extends BaseEntityMapper<OrderLine> {
        
        }
        
      • CRUD使用示例:
        @SpringBootTest(classes=SamplesApplication.class)
        public class OrderMapperTest {
        
            @Autowired
            private OrderMapper orderMapper;
        
            @Autowired
            private OrderLineMapper orderLineMapper;
        
            @Autowired
            private DataSourceTransactionManager dataSourceTransactionManager;
        
            protected <T> void doInTransaction(Supplier<T> 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<OrderLine> 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<String,Object> orderUpdateColumns = MapLambdaBuilder.<Order>ofEmpty()
                        .withOverride(Order::getOrderStatus, targetOrderStatus)
                        .withOverride(Order::getRemark, "已付款,请发顺丰快递!")
                        .withOverride(Order::getUpdateTime, nowTime)
                        .build();
                orderMapper.updateById(orderId, orderUpdateColumns); //更新主订单
        
                Map<String,Object> orderLineUpdateColums = MapLambdaBuilder.<OrderLine>ofEmpty()
                        .withOverride(OrderLine::getOrderStatus, targetOrderStatus)
                        .withOverride(OrderLine::getUpdateTime, nowTime)
                        .build();
                QueryCriteria<OrderLine> 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<ID> 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<OrderLine> 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不支持联合主键(复合主键)怎么办?试试M

        本文链接:https://www.haomeiwen.com/subject/wpqiyrtx.html