【实时数仓】DWM层订单宽表之维表关联异步查询(续)、DWM层支付宽表需求分析、需求实现(源码)

news2024/11/17 9:39:00

文章目录

  • 一 DWM层-订单宽表
    • 1 维表关联代码实现
      • (1)优化2:异步查询
        • a 关联省市维度
        • b 关联SKU维度
        • c 关联SPU维度
        • d 关联品类维度
        • e 关联品牌维度
        • f 最终结果展示
      • (2)结果写入kafka sink
  • 二 DWM层-支付宽表
    • 1 需求分析与思路
    • 2 需求实现
      • (1)创建支付实体类PaymentInfo
      • (2)创建支付宽表实体类PaymentWide
      • (3)读取数据
      • (4)指定水位线并提取事件时间字段(待优化)
      • (5)封装日期转换工具类
      • (6)修改后版本
      • (7)线程安全的日期转换工具类
      • (8)抽取Flink应用基类
      • (9)支付表和订单宽表双流join并写入到kafka
      • (10)测试

一 DWM层-订单宽表

1 维表关联代码实现

(1)优化2:异步查询

a 关联省市维度

// TODO 9 和地区维度进行关联
SingleOutputStreamOperator<OrderWide> orderWideWithProvinceDS = AsyncDataStream.unorderedWait(
        orderWideWithUserDS,
        new DimAsyncFunction<OrderWide>("DIM_BASE_PROVINCE") {
            // name
            // area_code
            // iso_code
            // iso_3166_2
            @Override
            public void join(OrderWide orderWide, JSONObject dimJsonObj) throws Exception {
                orderWide.setProvince_name(dimJsonObj.getString("NAME"));
                orderWide.setProvince_area_code("AREA_CODE");
                orderWide.setProvince_iso_code("ISO_CODE");
                orderWide.setProvince_3166_2_code("ISO_3166_2");
            }

            @Override
            public String getKey(OrderWide orderWide) {
                return orderWide.getProvince_id().toString();
            }
        },
        60,
        TimeUnit.SECONDS
);

orderWideWithProvinceDS.print();

测试

bin/maxwell-bootstrap --user maxwell  --password 123456 --host hadoop101  --database gmall2022 --table base_province --client_id maxwell_1

模拟生成业务数据,验证结果。

在这里插入图片描述

b 关联SKU维度

// TODO 10 和sku维度进行关联
SingleOutputStreamOperator<OrderWide> orderWideWithSkuDS = AsyncDataStream.unorderedWait(
        orderWideWithProvinceDS,
        new DimAsyncFunction<OrderWide>("DIM_SKU_INFO") {
            @Override
            public void join(OrderWide orderWide, JSONObject jsonObject) throws Exception {
                orderWide.setSku_name(jsonObject.getString("SKU_NAME"));
                orderWide.setCategory3_id(jsonObject.getLong("CATEGORY3_ID"));
                orderWide.setSpu_id(jsonObject.getLong("SPU_ID"));
                orderWide.setTm_id(jsonObject.getLong("TM_ID"));
            }

            @Override
            public String getKey(OrderWide orderWide) {
                return String.valueOf(orderWide.getSku_id());
            }
        }, 60, TimeUnit.SECONDS);

初始化SKU维度数据到Hbase(通过Maxwell的Bootstrap)

bin/maxwell-bootstrap --user maxwell  --password 123456 --host hadoop101  --database gmall2022 --table sku_info --client_id maxwell_1

c 关联SPU维度

SingleOutputStreamOperator<OrderWide> orderWideWithSpuDS = AsyncDataStream.unorderedWait(
        orderWideWithSkuDS,
        new DimAsyncFunction<OrderWide>("DIM_SPU_INFO") {
            @Override
            public void join(OrderWide orderWide, JSONObject jsonObject) throws Exception {
                orderWide.setSpu_name(jsonObject.getString("SPU_NAME"));
            }

            @Override
            public String getKey(OrderWide orderWide) {
                return String.valueOf(orderWide.getSpu_id());
            }
        }, 60, TimeUnit.SECONDS);
bin/maxwell-bootstrap --user maxwell  --password 123456 --host hadoop101  --database gmall2022 --table spu_info --client_id maxwell_1

d 关联品类维度

SingleOutputStreamOperator<OrderWide> orderWideWithCategory3DS = AsyncDataStream.unorderedWait(
        orderWideWithSpuDS, 
        new DimAsyncFunction<OrderWide>("DIM_BASE_CATEGORY3") {
            @Override
            public void join(OrderWide orderWide, JSONObject jsonObject) throws Exception {
                orderWide.setCategory3_name(jsonObject.getString("NAME"));
            }

            @Override
            public String getKey(OrderWide orderWide) {
                return String.valueOf(orderWide.getCategory3_id());
            }
        }, 60, TimeUnit.SECONDS);
bin/maxwell-bootstrap --user maxwell  --password 123456 --host hadoop101  --database gmall2022 --table base_category3 --client_id maxwell_1

e 关联品牌维度

SingleOutputStreamOperator<OrderWide> orderWideWithTmDS = AsyncDataStream.unorderedWait(
        orderWideWithCategory3DS, new DimAsyncFunction<OrderWide>("DIM_BASE_TRADEMARK") {
            @Override
            public void join(OrderWide orderWide, JSONObject jsonObject) throws Exception {
                orderWide.setTm_name(jsonObject.getString("TM_NAME"));
            }

            @Override
            public String getKey(OrderWide orderWide) {
                return String.valueOf(orderWide.getTm_id());
            }
        }, 60, TimeUnit.SECONDS);
bin/maxwell-bootstrap --user maxwell  --password 123456 --host hadoop101  --database gmall2022 --table base_trademark --client_id maxwell_1

f 最终结果展示

模拟数据生成,查询结果

在这里插入图片描述

至此订单宽表准备完成,执行最终写回kafka中的操作。

在这里插入图片描述

(2)结果写入kafka sink

// TODO 14 将订单宽表数据写回到kafka的dwd_order_wide主题中
// JSON.parseObject(jsonStr) : 将json格式的字符串转换为JSON对象
// JSON.parseObject(jsonStr,类型) : 将json格式的字符串转换为指定格式对象
// JSON.toJSONString(orderWide) : 将对象转换为JSON格式字符串
orderWideWithTmDS
        // 将OrderWide对象转换为JSON格式字符串
        .map(orderWide -> JSON.toJSONString(orderWide))
        .addSink(
        // 放到同一个主题中
        MyKafkaUtil.getKafkaSink("dwm_order_wide")
);

启动kafka消费者

kfkcon.sh dwm_order_wide

模拟生成数据,kafka中结果如下
在这里插入图片描述

订单宽表已完成,总体流程如下
在这里插入图片描述
在这里插入图片描述

二 DWM层-支付宽表

1 需求分析与思路

支付宽表的目的,最主要的原因是支付表没有到订单明细,支付金额没有细分到商品上,没有办法统计商品级的支付状况。

所以支付宽表的核心就是要把支付表的信息与订单明细关联上。

解决方案有两个

  • 一个是把订单明细表(或者宽表)输出到Hbase上,在支付宽表计算时查询hbase,这相当于把订单明细作为一种维度进行管理。
  • 一个是用流的方式接收订单明细,然后用双流join方式进行合并。因为订单与支付产生有一定的时差。所以必须用intervalJoin来管理流的状态时间,保证当支付到达时订单明细还保存在状态中。

总体流程如下

在这里插入图片描述

2 需求实现

(1)创建支付实体类PaymentInfo

package com.hzy.gmall.realtime.beans;

import lombok.Data;
import java.math.BigDecimal;
/**
 * Desc: 支付信息实体类
 */
@Data
public class PaymentInfo {
    Long id;
    Long order_id;
    Long user_id;
    BigDecimal total_amount;
    String subject;
    String payment_type;
    String create_time;
    String callback_time;   // 支付成功的时间需要看回调时间而不是创建时间
}

(2)创建支付宽表实体类PaymentWide

package com.hzy.gmall.realtime.beans;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.beanutils.BeanUtils;

import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;

/**
 * Desc: 支付宽表实体类
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class PaymentWide {

    Long payment_id;
    String subject;
    String payment_type;
    String payment_create_time;
    String callback_time;
    Long detail_id;
    Long order_id ;
    Long sku_id;
    BigDecimal order_price ;
    Long sku_num ;
    String sku_name;
    Long province_id;
    String order_status;
    Long user_id;
    BigDecimal total_amount;
    BigDecimal activity_reduce_amount;
    BigDecimal coupon_reduce_amount;
    BigDecimal original_total_amount;
    BigDecimal feight_fee;
    BigDecimal split_feight_fee;
    BigDecimal split_activity_amount;
    BigDecimal split_coupon_amount;
    BigDecimal split_total_amount;
    String order_create_time;

    String province_name;//查询维表得到
    String province_area_code;
    String province_iso_code;
    String province_3166_2_code;
    Integer user_age ;
    String user_gender;

    Long spu_id;     //作为维度数据 要关联进来
    Long tm_id;
    Long category3_id;
    String spu_name;
    String tm_name;
    String category3_name;

    public PaymentWide(PaymentInfo paymentInfo, OrderWide orderWide){
        mergeOrderWide(orderWide);
        mergePaymentInfo(paymentInfo);
    }

    public void  mergePaymentInfo(PaymentInfo paymentInfo  )  {
        if (paymentInfo != null) {
            try {
                BeanUtils.copyProperties(this,paymentInfo);
                payment_create_time=paymentInfo.create_time;
                payment_id = paymentInfo.id;
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }
    }

    public void  mergeOrderWide(OrderWide orderWide  )  {
        if (orderWide != null) {
            try {
                BeanUtils.copyProperties(this,orderWide);
                order_create_time=orderWide.create_time;
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }
    }
}

(3)读取数据

package com.hzy.gmall.realtime.app.dwm;
/**
 * 支付宽表的准备
 */
public class PaymentWideApp {
    public static void main(String[] args) throws Exception {
        //TODO 1.基本环境准备
        //1.1 流处理环境
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        //1.2 设置并行度
        env.setParallelism(4);

        //TODO 2.检查点相关设置(略)

        //TODO 3.从Kafka中读取数据
        //3.1 声明消费的主题以及消费者组
        String paymentInfoSourceTopic = "dwd_payment_info";
        String orderWideSourceTopic = "dwm_order_wide";
        String groupId = "payment_wide_app_group";
        //3.2 获取kafka消费者
        FlinkKafkaConsumer<String> paymentInfoSource = MyKafkaUtil.getKafkaSource(paymentInfoSourceTopic, groupId);
        FlinkKafkaConsumer<String> orderWideSource = MyKafkaUtil.getKafkaSource(orderWideSourceTopic, groupId);
        //3.3 读取数据  封装为流
        DataStreamSource<String> paymentInfoStrDS = env.addSource(paymentInfoSource);
        DataStreamSource<String> orderWideStrDS = env.addSource(orderWideSource);

        //TODO 4.对流中数据类型进行转换    String ->实体对象
        //支付
        SingleOutputStreamOperator<PaymentInfo> paymentInfoDS = paymentInfoStrDS.map(jsonStr -> JSON.parseObject(jsonStr, PaymentInfo.class));
        //订单宽表
        SingleOutputStreamOperator<OrderWide> orderWideInfoDS = orderWideStrDS.map(jsonStr -> JSON.parseObject(jsonStr, OrderWide.class));

        paymentInfoDS.print("支付数据:");
        orderWideInfoDS.print("订单宽表:");
        
        env.execute();
    }
}

开启BaseDBApp、OrderWideApp、PaymentWideApp,模拟生成业务数据,查看结果。

(4)指定水位线并提取事件时间字段(待优化)

//TODO 5.指定Watermark并提取事件时间字段
//支付
SingleOutputStreamOperator<PaymentInfo> paymentInfoWithWatermarkDS = paymentInfoDS.assignTimestampsAndWatermarks(
        WatermarkStrategy.<PaymentInfo>forBoundedOutOfOrderness(Duration.ofSeconds(3))
                .withTimestampAssigner(
                        new SerializableTimestampAssigner<PaymentInfo>() {
                            @Override
                            public long extractTimestamp(PaymentInfo paymentInfo, long recordTimestamp) {
                                String callbackTimeStr = paymentInfo.getCallback_time();
                                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                                Long ts = null;
                                try {
                                    ts = sdf.parse(callbackTimeStr).getTime();
                                } catch (ParseException e) {
                                    e.printStackTrace();
                                }
                                return ts;
                            }
                        }
                )
);
// 订单宽表
SingleOutputStreamOperator<OrderWide> orderWideWithWatermarkDS = orderWideInfoDS.assignTimestampsAndWatermarks(
        WatermarkStrategy.<OrderWide>forBoundedOutOfOrderness(Duration.ofSeconds(3))
                .withTimestampAssigner(
                        new SerializableTimestampAssigner<OrderWide>() {
                            @Override
                            public long extractTimestamp(OrderWide orderWide, long recordTimestamp) {
                                String createTimeStr = orderWide.getCreate_time();
                                // 每调用一次创建一个对象,不好
                                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-HH-dd HH:mm:ss");
                                Long ts = null;
                                try {
                                    ts = sdf.parse(createTimeStr).getTime();
                                } catch (ParseException e) {
                                    e.printStackTrace();
                                }
                                return ts;
                            }
                        }
                )
);

(5)封装日期转换工具类

package com.hzy.gmall.realtime.utils;
/**
 * 日期转换的工具类
 */
public class DateTimeUtil {
    private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    public static Long toTs(String dateStr){
        Long ts = null;
        try {
            ts = sdf.parse(dateStr).getTime();
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return ts;
    }
}

(6)修改后版本

//TODO 5.指定Watermark并提取事件时间字段
//支付
SingleOutputStreamOperator<PaymentInfo> paymentInfoWithWatermarkDS = paymentInfoDS.assignTimestampsAndWatermarks(
        WatermarkStrategy.<PaymentInfo>forBoundedOutOfOrderness(Duration.ofSeconds(3))
                .withTimestampAssigner(
                        new SerializableTimestampAssigner<PaymentInfo>() {
                            @Override
                            public long extractTimestamp(PaymentInfo paymentInfo, long recordTimestamp) {
                                return DateTimeUtil.toTs(paymentInfo.getCallback_time());
                            }
                        }
                )
);
// 订单宽表
SingleOutputStreamOperator<OrderWide> orderWideWithWatermarkDS = orderWideInfoDS.assignTimestampsAndWatermarks(
        WatermarkStrategy.<OrderWide>forBoundedOutOfOrderness(Duration.ofSeconds(3))
                .withTimestampAssigner(
                        new SerializableTimestampAssigner<OrderWide>() {
                            @Override
                            public long extractTimestamp(OrderWide orderWide, long recordTimestamp) {
                                return DateTimeUtil.toTs(orderWide.getCreate_time());
                            }
                        }
                )
);

(7)线程安全的日期转换工具类

SimpleDateFormat是线程不安全的,在JDK1.8之后,使用DateTimeFormatter替换。

package com.hzy.gmall.realtime.utils;
/**
 * 日期转换的工具类
 */
public class DateTimeUtil {
//    private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    private static DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    // 将日期对象转换为字符串
    public static String toYMDHMS(Date date){
        LocalDateTime localDateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
        String dateStr = dtf.format(localDateTime);
        return dateStr;
    }

    // 将字符串日期转换为毫秒数
    public static Long toTs(String dateStr){
        //Date == LocalDateTime   Calendar == Instant
        LocalDateTime localDateTime = LocalDateTime.parse(dateStr, dtf);
        long ts = localDateTime.toInstant(ZoneOffset.of("+8")).toEpochMilli();
        return ts;
    }
}

(8)抽取Flink应用基类

package com.hzy.gmall.realtime.app.dwd;

public abstract class Base {
    public void entry() throws Exception {
        //TODO 1 基本环境准备
        //流处理环境
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        // 设置并行度
        env.setParallelism(4);

        //TODO 2 检查点设置
        //开启检查点
        env.enableCheckpointing(5000L, CheckpointingMode.EXACTLY_ONCE);
        // 设置检查点超时时间
        env.getCheckpointConfig().setCheckpointTimeout(60000L);
        // 设置重启策略
        env.setRestartStrategy(RestartStrategies.fixedDelayRestart(3,3000L));
        // 设置job取消后,检查点是否保留
        env.getCheckpointConfig().enableExternalizedCheckpoints(CheckpointConfig.ExternalizedCheckpointCleanup.RETAIN_ON_CANCELLATION);
        // 设置状态后端 -- 基于内存 or 文件系统 or RocksDB
        env.setStateBackend(new FsStateBackend("hdfs://hadoop101:8020/ck/gmall"));
        // 指定操作HDFS的用户
        System.setProperty("HADOOP_USER_NAME","hzy");

        executeBiz(env);

        env.execute();
    }

    public abstract void executeBiz(StreamExecutionEnvironment env);
}
package com.hzy.gmall.realtime.app.dwd;

public class dwsApp extends Base{
    public static void main(String[] args) throws Exception {
        Base base = new dwsApp();
        base.entry();
    }

    @Override
    public void executeBiz(StreamExecutionEnvironment env) {
        env.addSource(MyKafkaUtil.getKafkaSource("",""));
    }
}

(9)支付表和订单宽表双流join并写入到kafka

// TODO 7 支付和订单宽表的双流join
SingleOutputStreamOperator<PaymentWide> paymentWideDS = paymentInfoKeyedDS
        .intervalJoin(orderWideKeyedDS)
        .between(Time.minutes(-30), Time.minutes(0))
        .process(
                new ProcessJoinFunction<PaymentInfo, OrderWide, PaymentWide>() {
                    @Override
                    public void processElement(PaymentInfo paymentInfo, OrderWide orderWide, Context ctx, Collector<PaymentWide> out) throws Exception {
                        out.collect(new PaymentWide(paymentInfo, orderWide));
                    }
                }
        );

paymentWideDS.print(">>>>");

// TODO 8 将支付宽表数据写到kafka的dwm_payment_wide
paymentWideDS
        .map(paymentWide -> JSON.toJSONString(paymentWide))
        .addSink(MyKafkaUtil.getKafkaSink("dwm_payment_wide"));

(10)测试

启动三个应用程序和一个kafka消费者,模拟业务数据的生成,查看最终结果。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/107677.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

界面控件DevExpress WinForm v22.1——拥有全新的WXI调色板

DevExpress WinForm拥有180组件和UI库&#xff0c;能为Windows Forms平台创建具有影响力的业务解决方案。DevExpress WinForm能完美构建流畅、美观且易于使用的应用程序&#xff0c;无论是Office风格的界面&#xff0c;还是分析处理大批量的业务数据&#xff0c;它都能轻松胜任…

车载以太网解决方案,你知多少?

近年来&#xff0c;为了满足智能网联汽车的开发要求&#xff0c;车载以太网技术开始逐渐进入人们的视野。而以太网技术已经成为下一代车载络架构的趋势之一&#xff0c;其发展之迅猛&#xff0c;使得各主机厂纷纷产生了浓厚的兴趣并投入研发。 一 为什么使用车载以太网 | 对高…

UE4 GIS Cesium for Unreal插件使用

第一步&#xff1a;安装Cesium for Unreal插件 如果尚未安装&#xff0c;请先安装Cesium for Unreal插件。 在虚幻引擎市场上打开Cesium for Unreal插件页面。2. 登录虚幻引擎商城&#xff0c;并单击免费按钮&#xff0c;将插件安装在虚幻引擎中。 第二步&#xff1a;创建项…

这里有 10 个省时间的 PyCharm 技巧

0. PyCharm 常用快捷键 1. 查看使用库源码 经常听人说&#xff0c;多看源码。源码不仅能帮我们搞清楚运行机制&#xff0c;还能学习优秀的库或者框架的最佳实践。 调用库时&#xff0c;你可以在你好奇的几乎任何地方点击 CommandB&#xff0c;就可以很方便的跳转到源码里的类&…

电商项目6:商品模块-品牌管理

商品模块-品牌管理1、逆向工程生成菜单2、优化逆向生成的前端工程2.1、优化显示状态1、逆向工程生成菜单 将逆向工程生成的两个vue文件放置到前端项目&#xff0c;可以参考电商项目2逆向工程生成 将其两个vue文件复制到product目录下 然后重启前端项目 只有查询&#xff0c;…

【算法】子序列问题合集

前言 动态规划的核心设计思想是数学归纳法 假如我们想证明一个数学结论&#xff1a; 那么先假设这个结论在 k < n 时成立想办法推导证明出 k n 的时候此结论也成立。是需要一个 dp 数组嘛&#xff1f; 可以假设 dp[0...i - 1] 都已经被算出来了然后问自己&#xff1a;怎么…

记录Android Studio连接华为(nova)手机鸿蒙系统踩过的坑

目录 安装Android studio 安装Google USE Driver 查看华为手机的安卓版本 设置开发者模式 安装华为手机助手 重启Android studio 总结 安装Android studio 我主要参考的是这篇文章&#xff1a;Android基础&#xff08;android studio最详细基础使用功略&#xff09;_手下…

14考虑电动汽车可调度潜力的充电站两阶段市场投标策略

参考文献 考虑电动汽车可调度潜力的充电站两阶段市场投标策略——詹祥澎&#xff08;电力系统自动化,2021&#xff09; 主要内容 在电力市场环境下,充电站优化投标策略能降低电力成本&#xff0c;甚至通过售电获取收益。本程序考虑了电动汽车成为柔性储荷资源的潜力&#xf…

【目标检测】只需一张图~YOLOv5原理懂了~

目录 一、简介 二、模型结构 1.整体结构图 2.Backbone&#xff08;CSPDarknet&#xff09; 3.SPPF&#xff08;Spatial Pyramid Pooling - Fast&#xff09; 4.Neck&#xff08;FPNPAN&#xff09; 5.Head 三、anchor编解码 1.anchor编码 2.anchor解码 四、损失函数 …

一文读懂Go函数调用

导读&#xff5c;Go的函数调用时参数是通过栈传递还是寄存器传递&#xff1f;使用哪个版本的Go语言能让程序运行性能提升5%&#xff1f;腾讯后台开发工程师涂明光将带你由浅入深了解函数调用&#xff0c;并结合不同版本Go进行实操解答。函数调用基本概念1&#xff09;调用者cal…

【服务器数据恢复】Linux服务器重装系统后出现空白超级块的数据恢复案例

服务器数据恢复环境&#xff1a; 某品牌X系列服务器&#xff1b; linux操作系统&#xff1b; 4块SAS接口硬盘组建raid5磁盘阵列。 服务器故障&检测&#xff1a; 服务器运行过程中由于未知原因突然瘫痪&#xff0c;用户为故障服务器重新安装操作系统&#xff0c;安装完成后发…

【车载开发系列】UDS诊断---基于事件响应($0x86)

【车载开发系列】UDS诊断—基于事件响应&#xff08;$0x86&#xff09; 诊断---基于事件响应&#xff08;$0x86&#xff09;【车载开发系列】UDS诊断---基于事件响应&#xff08;$0x86&#xff09;一.概念定义二.注意事项三.报文格式1&#xff09;请求报文2&#xff09;肯定响应…

Java+MySQL基于ssm家教服务平台

随着互联网趋势的到来&#xff0c;各行各业都在考虑利用互联网将自己推广出去&#xff0c;最好方式就是建立自己的互联网系统&#xff0c;并对其进行维护和管理。在现实运用中&#xff0c;应用软件的工作规则和开发步骤&#xff0c;采用SSM框架建设家教服务平台。 本毕业设计主…

11个案例讲透 Python 函数参数

今天给大家分享一下自己整理的一篇 Python 参数的内容&#xff0c;内容非常的干&#xff0c;全文通过案例的形式来理解知识点&#xff0c;自认为比网上 80% 的文章讲的都要明白&#xff0c;如果你是入门不久的 python 新手&#xff0c;相信本篇文章应该对你会有不小的帮助。 接…

第5章 高级SQL

第5章 高级SQL 考试范围&#xff1a; 5.2 -5.3 考试题型&#xff1a; 计算题 考试内容&#xff1a; 函数、过程和触发器的概念 会定义和调用函数、过程 会定义触发器 函数、过程和触发器的概念 函数&&过程 存储过程和函数是一组为了完成特定功能的SQL语句集&…

如何用pgloader将Zabbix的MySQL数据库迁移到PostgreSQL数据库?

感谢本文作者 董玉凡 &#xff0c;Zabbix工程师 摘 要 ►今天我们使用一款工具pgloader来进行从Zabbix的MySQL数据库将数据迁移到PostgreSQL数据库。 ►pgloader是一款开源软件项目&#xff0c;可以将各种来源的数据加载到PostgreSQL当中&#xff0c;可以支持动态读取的数据…

计算机毕设Python+Vue寻迹边境丹东旅游网站(程序+LW+部署)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

2022中国产业数字化发展成熟度行业指数分析—— 重视差异,结合自身要素禀赋,推进产业精细化治理

易观分析&#xff1a;随着新一轮数字技术加速渗透到各行各业&#xff0c;发展壮大战略性新兴产业成为了现代化产业体系的新动力引擎。战略性新兴产业代表了新一轮科技革命和产业变革的方向&#xff0c;既是推进新型工业化的主要抓手&#xff0c;也是中国式现代化建设必不可少的…

【UE4 第一人称射击游戏】03-再生护甲和伤害功能

效果&#xff1a; 步骤&#xff1a; 1.打开“ThirdPersonCharacter”&#xff0c;添加如下节点&#xff1a; 如果护甲量<100%&#xff0c;就每秒1% 2.新建一个函数&#xff0c;命名为“TakeDamage5%” 每次执行该函数就减少5%的护甲量&#xff0c;如果护甲量<0&#…

NeurIPS'22 | GBA:面向搜推广模型的同步和异步自由切换的训练范式

丨目录&#xff1a; 搜推广增量迭代挑战 GBA的诞生 GBA的收敛性分析 GBA工程实现 GBA实验效果 未来展望近日&#xff0c;阿里巴巴在国际顶级机器学习会议NeurIPS 2022上发表了新的自研训练模式Gloabl Batch gradients Aggregation GBA&#xff08;论文链接&#xff1a;https://…