RTSP视频流相关的一些操作

播放rtsp camera 内容

  • 端口554在网络通信中用于Real Time Streaming Protocol(RTSP)。
gst-launch-1.0 playbin uri=rtsp://admin:WANGfengtu12@10.0.20.190:554/client0x
gst-launch-1.0 playbin uri=rtsp://admin:WANGfengtu12@10.0.20.61:554/client1x

gst-launch-1.0 rtspsrc location=rtsp://admin:WANGfengtu12@10.0.20.70:554/client0x ! rtph264depay ! h264parse ! decodebin ! autovideosink
gst-launch-1.0 rtspsrc location=rtsp://admin:WANGfengtu12@10.0.20.61:554/client1x ! rtph264depay ! h264parse ! decodebin ! autovideosink
  • 尝试使用v4l2 去解码
gst-launch-1.0 rtspsrc location=rtsp://admin:WANGfengtu12@10.0.20.61:554/client1x latency=10 ! rtph264depay ! h264parse ! v4l2h264dec capture-io-mode=4 ! v4l2convert output-io-mode=5 capture-io-mode=4 ! autovideosink sync=false

在这里插入图片描述

Ref

https://gstreamer.freedesktop.org/documentation/tutorials/playback/hardware-accelerated-video-decoding.html?gi-language=c
https://github.com/uutzinger/camera/blob/master/RTSP_RTP_gstreamer.md

NNStreamer

Env

  • Ubuntu18.04
  • x86-64
# 安装
$ sudo add-apt-repository ppa:nnstreamer/ppa
$ sudo apt-get update
$ sudo apt-get install nnstreamer

$ sudo add-apt-repository ppa:nnstreamer-example/ppa
$ sudo apt-get update
$ sudo apt-get install nnstreamer-example

sudo apt install nnstreamer-tensorflow2-lite
$ cd /usr/lib/nnstreamer/bin

./nnstreamer_example_pose_estimation_tflite 
python3 nnstreamer_example_object_detection_tflite.py 
  • 使用 rtsp 流去做推理 nnstreamer_example_object_detection_tflite.py
        self.pipeline = Gst.parse_launch(
            'rtspsrc location=rtsp://admin:WANGfengtu12@10.0.20.61:554/client1x ! rtph264depay ! h264parse ! decodebin ! videoconvert ! videoscale ! '
            'video/x-raw,width=640,height=480,format=RGB ! tee name=t_raw '
            't_raw. ! queue leaky=2 max-size-buffers=2 ! videoscale ! video/x-raw,width=300,height=300 ! tensor_converter ! '
            'tensor_transform mode=arithmetic option=typecast:float32,add:-127.5,div:127.5 ! '
            'tensor_filter framework=tensorflow-lite model=' + self.tflite_model + ' ! '
            'tensor_decoder mode=bounding_boxes option1=mobilenet-ssd option2='
            + self.tflite_label + ' option3=' + self.tflite_box_prior + ' option4=640:480 option5=300:300 !'
            'compositor name=mix sink_0::zorder=2 sink_1::zorder=1 ! videoconvert ! ximagesink '
            't_raw. ! queue leaky=2 max-size-buffers=10 ! mix. '
        )
  • yolov5
gst-launch-1.0 v4l2src ! videoscale ! videoconvert ! video/x-raw,width=320,height=320,format=RGB,framerate=30/1,pixel-aspect-ratio=1/1 ! tee name=t   t. ! queue ! tensor_converter ! other/tensors,num_tensors=1,types=uint8,format=static,dimensions=3:320:320:1 !     tensor_transform mode=arithmetic option=typecast:float32,add:0.0,div:255.0 ! queue leaky=2 max-size-buffers=2 !     tensor_filter framework=tensorflow2-lite model=./yolov5s-fp16-320.tflite !     other/tensors,num_tensors=1,types=float32,format=static,dimensions=85:6300:1:1 !     tensor_decoder mode=bounding_boxes option1=yolov5 option2=./coco.txt option4=320:320 option5=320:320 !     video/x-raw,width=320,height=320,format=RGBA ! mix.sink_0   t. ! queue ! mix.sink_1 compositor name=mix sink_0::zorder=2 sink_1::zorder=1 ! videoconvert ! ximagesink

gst-launch-1.0 rtspsrc location=rtsp://admin:WANGfengtu12@10.0.20.61:554/client1x ! rtph264depay ! h264parse ! decodebin ! videoconvert ! video/x-raw,width=320,height=320,format=RGB,framerate=30/1,pixel-aspect-ratio=1/1 ! tee name=t   t. ! queue ! tensor_converter ! other/tensors,num_tensors=1,types=uint8,format=static,dimensions=3:320:320:1 !     tensor_transform mode=arithmetic option=typecast:float32,add:0.0,div:255.0 ! queue leaky=2 max-size-buffers=2 !     tensor_filter framework=tensorflow2-lite model=./yolov5s-fp16-320.tflite !     other/tensors,num_tensors=1,types=float32,format=static,dimensions=85:6300:1:1 !     tensor_decoder mode=bounding_boxes option1=yolov5 option2=./coco.txt option4=320:320 option5=320:320 !     video/x-raw,width=320,height=320,format=RGBA ! mix.sink_0   t. ! queue ! mix.sink_1 compositor name=mix sink_0::zorder=2 sink_1::zorder=1 ! videoconvert ! ximagesink

使用opencv播放rtsp流

py

import cv2 as cv


cap = cv.VideoCapture('rtsp://admin:WANGfengtu12@10.0.20.61:554/client1x',cv.CAP_GSTREAMER)
while cv.waitKey(1) < 0:
    hasFrame, frame = cap.read()

    if not hasFrame:
        break

    cv.imshow("rtsp", frame)

cpp

cv::VideoCapture cap;
cap.open("rtsp://admin:WANGfengtu12@10.0.20.61:554/client1x",cv::CAP_GSTREAMER);


cv::Mat frame;

while(cv::waitKey(1) < 0) // Press any key to exit
{
    if (!cap.read(frame))
    {
        cerr << "No frames grabbed!\n";
        break;
    }
}
}   

Ref

  • https://bbs.huaweicloud.com/blogs/315157

Q&A

python 使用gstreamer遇到的问题

  • No matching distribution found for gi
  • https://stackoverflow.com/questions/71369726/no-module-named-gi
sudo apt install libcairo2-dev libxt-dev libgirepository1.0-dev

pip install pycairo PyGObject

ffmpeg拉取rtsp流播放

ffmpeg -f v4l2 -i /dev/video0  -s 1280X720 -r 24 -vcodec libx264 -f rtsp rtsp://10.0.20.193:554/stream

ffplay -rtsp_transport tcp -fflags nobuffer rtsp://10.0.20.193/test

rk3588 使用gstreamer编解码,OpenEuler上

  • 将硬编码相关的mpp 拷贝到设备上,https://gitee.com/wangyx0704/roc-rk3588s-pc-mppcodec
  • 修改设备/dev/mpp_service 权限
# 下载相关的git 仓库
git clone https://gitee.com/wangyx0704/gst-d-softbus-sink.git
git clone https://gitee.com/wangyx0704/roc-rk3588s-pc-mppcodec.git

#安装相关的依赖
yum install opencv*  gcc-c++.aarch64  gcc.aarch64 -y
dnf install eigen3
dnf install -y gstreamer1 gstreamer1-devel gstreamer1-plugins-base gstreamer1-plugins-good gstreamer1-plugins-bad-free

dnf install -y gstreamer1* git make  cmake unzip pkg-config
rpm -e gstreamer1-plugins-base-help.noarch

#使用仓库中下载完的软件包,替换已经安装好的软件包
cd gst-d-softbus-sink/rpms
yum install -y gstreamer1-plugins-base-1.19.2/*.rpm
yum install -y gstreamer1-rtsp-server-1.19.2/*.rpm
将`roc-rk3588s-pc-mppcodec` 编解码库移动到系统目录`/usr/lib64`
  • 常使用的pipeline的用法

# 解码
# 硬解
gst-launch-1.0 rtspsrc location="rtsp://admin:WANGfengtu12@10.0.20.61:554/client1x" latency=0 drop-on-latency=true protocols=tcp ! rtph264depay ! h264parse ! mppvideodec ! video/x-raw,format=BGR ! appsink

# 软解
gst-launch-1.0 rtspsrc location="rtsp://admin:WANGfengtu12@10.0.20.61:554/client1x" latency=0 drop-on-latency=true protocols=tcp ! rtph264depay ! h264parse ! avdec_h264 ! videoconvert ! video/x-raw,format=BGR ! appsink


# 编码
# 硬编
gst-launch-1.0 appsrc ! videoconvert ! mppvp8enc ! video/x-vp8, mapping=/stream1 ! rtspclientsink latency=0 location=rtsp://10.0.20.193:554/test

gst-launch-1.0 videotestsrc ! video/x-raw,width=1280,height=720 ! videoconvert ! mpph264enc ! video/x-h264, mapping=/stream1 ! rtspclientsink latency=0 location=rtsp://10.0.20.193:554/test

gst-launch-1.0 videotestsrc ! videoconvert ! mpph264enc ! rtspclientsink latency=0 location=rtsp://10.0.20.193:554/test

# 软编
gst-launch-1.0 videotestsrc ! videoconvert ! vp8enc ! rtspclientsink latency=0 location=rtsp://10.0.20.193:554/test

# 不能同时支持 软硬解码
gst-launch-1.0 rtspsrc location=rtsp://10.0.20.193/st1 latency=0 protocols=udp ! queue ! rtph264depay ! h264parse ! avdec_h264 ! videoconvert ! video/x-raw, format=BGR ! videoconvert ! video/x-raw,format=YUY2,width=1280,height=720 ! mpph264enc ! rtspclientsink latency=100 location=rtsp://10.0.20.193:554/test

RK3588 Ubuntu使用

sudo apt install gstreamer1.0-rtsp
sudo apt install gstreamer1.0-rockchip1

OpenEuler 上面安装GStreamer

OE 22.03

sudo dnf install gstreamer*

# 目录 gstreamer1-rtsp-server-1.19.2
sudo rmp -Uvh *.rpm
# 直接远程安装
sudo dnf install gstreamer1-rtsp-server*

# rtspsrc
sudo dnf install gstreamer1-plugins-good*

# h264parse
sudo dnf install gstreamer1-plugins-bad*

# avdec_h264
sudo dnf install libgstlibav*

OE 20.03

# 卸载旧包
rpm -e gstreamer1-plugins-base-help.noarch

# 在下面目录依次执行
yum install *.rpm
# gstreamer1-plugins-base-1.19.2
#  gstreamer1-rtsp-server-1.19.2 

rk3588 gstreamer pipeline 的使用

# 硬件编码
gst-launch-1.0 videotestsrc ! videoconvert ! mpph264enc ! rtspclientsink latency=0 location=rtsp://10.0.20.193:554/test

在这里插入图片描述

# 软件编码
gst-launch-1.0 videotestsrc ! videoconvert ! vp8enc ! rtspclientsink latency=0 location=rtsp://10.0.20.193:554/test

# 软解软编
gst-launch-1.0 rtspsrc location=rtsp://10.0.20.193/st1 latency=0 protocols=udp ! queue ! rtph264depay ! h264parse ! avdec_h264 ! videoconvert ! video/x-raw, format=BGR ! videoconvert ! vp8enc ! rtspclientsink latency=100 location=rtsp://10.0.20.193:554/test

# 硬解硬编 (这种存在问题)
gst-launch-1.0 -v rtspsrc location=rtsp://10.0.20.193/st1 latency=0 ! rtph264depay ! h264parse ! mppvideodec ! videoconvert ! mpph264enc ! queue ! h264parse ! rtspclientsink location=rtsp://10.0.20.193:554/st2 latency=100

# 通过将mpp patch打上,重新编译内核 
export GST_VIDEO_CONVERT_USE_RGA=1
export GST_VIDEO_FLIP_USE_RGA=1
gst-launch-1.0 rtspsrc location=rtsp://10.0.20.193/input latency=0 protocols=udp ! queue ! rtph264depay ! h264parse ! mppvideodec ! videoconvert ! video/x-raw, format=BGR ! videoconvert ! video/x-raw,format=NV12 ! mpph264enc ! rtspclientsink latency=100 location=rtsp://10.0.20.193:554/test

Gstreamer server (完全不推荐)

1

#include <gst/gst.h>
#include <gst/rtsp-server/rtsp-server.h>

int main(int argc, char ** argv)
{
    GMainLoop *loop;
    GstRTSPMediaFactory *factory;

    char * pipe = "rtspsrc location=rtsp://10.0.20.193/st1 latency=0 protocols=udp ! queue ! rtph264depay ! h264parse ! avdec_h264 ! videoconvert ! video/x-raw, format=BGR ! videoconvert ! video/x-raw,format=YUY2,width=1280,height=720 ! mpph264enc ! rtspclientsink latency=100 location=rtsp://10.0.20.193:554/test";
    loop = g_main_loop_new(NULL, FALSE);

    factory = gst_rtsp_media_factory_new();
    gst_rtsp_media_factory_set_launch(factory, pipe);
    gst_rtsp_media_factory_set_shared(factory, TRUE);
    gst_rtsp_media_factory_set_enable_rtcp(factory, FALSE);

    g_main_loop_run(loop);
    return 0;
}
  • 编译选项
 # 错误
 gcc test_pipeline.c -o test_pipeline -lgstrtsp-1.0 `pkg-config --cflags --libs gstreamer-1.0` `pkg-config --cflags --libs gstreamer-plugins-base-1.0`
 # 正确
 gcc test_pipeline.c -o test_pipeline -lgstrtsp-1.0 `pkg-config --cflags --libs gstreamer-1.0` `pkg-config --cflags --libs gstreamer-rtsp-server-1.0`

2

#include <gst/gst.h>


int main(int argc, char **argv)
{
    GstElement *pipeline;
    GstBus * bus;
    GstMessage *msg;


    gst_init(&argc, &argv);

    pipeline = gst_parse_launch("rtspsrc location=rtsp://10.0.20.193/st1 latency=0 protocols=udp ! queue ! rtph264depay ! h264parse ! avdec_h264 ! videoconvert ! video/x-raw, format=BGR ! videoconvert ! video/x-raw,format=YUY2,width=1280,height=720 ! mpph264enc ! rtspclientsink latency=100 location=rtsp://10.0.20.193:554/test", NULL);

    gst_element_set_state(pipeline, GST_STATE_PLAYING);



    bus = gst_element_get_bus(pipeline);

    msg = gst_bus_timed_pop_filtered(bus, GST_CLOCK_TIME_NONE, GST_MESSAGE_ERROR | GST_MESSAGE_EOS);

    if(msg != NULL)
    {
        gst_message_unref(msg);
    }

    gst_object_unref(msg);

    gst_element_set_state(pipeline, GST_STATE_NULL);

    gst_object_unref(pipeline);
    return 0;
}
  • 编译选项
gcc test_pipeline_2.c -o test_pipeline_2 `pkg-config --cflags --libs gstreamer-1.0` `pkg-config --cflags --libs gstreamer-rtsp-server-1.0`

使用ffmpeg 拉流保存到本地

ffmpeg -i rtsp://admin:WANGfengtu12@10.0.20.70:554/client0x  -vcodec copy out.h264

ffmpeg 推送本地流

ffmpeg -re  -stream_loop -1 -i D:\workspace\test.mp4  -vcodec copy -rtsp_transport tcp -f rtsp rtsp://192.168.3.176:554/s1

ffmpeg -re  -i rtsp://192.168.1.103/car/EdgeCar2 -vcodec copy -rtsp_transport tcp -f rtsp rtsp://192.168.1.109:554/s1

ffmpeg 拉流转发

ffmpeg -i rtsp://10.0.20.193/st1 -s 1080*720 -vcodec copy -f rtsp -rtsp_transport tcp rtsp://10.0.20.193:554/test
ffmpeg -i rtsp://10.0.20.193/st1 -acodec copy -vcodec copy -f rtsp -rtsp_transport tcp rtsp://10.0.20.193:554/test

推送到指定服务器

ffmpeg -re -stream_loop -1 -i test.mp4  -s 1280*720 -vcodec h264 -f rtsp -rtsp_transport tcp rtsp://10.0.20.221:554/test
ffmpeg -re -stream_loop -1 -i .\10daojishi.mp4 -vcodec copy -acodec copy -f rtsp rtsp://10.0.20.109:554/test

使用nvidia 硬编解码 推流

ffmpeg -re -stream_loop -1 -i merge.mp4   -vcodec h264_nvenc -f rtsp -rtsp_transport udp rtsp://10.0.20.193:554/test

设置Gstreamer debug level

export GST_DEBUG=4

rtsp 流服务器

easy-darwin

ZLMediaKit

https://github.com/ZLMediaKit/ZLMediaKit/wiki/%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%9A%84%E5%90%AF%E5%8A%A8%E4%B8%8E%E5%85%B3%E9%97%AD
https://github.com/ZLMediaKit/ZLMediaKit/wiki/ZLMediaKit%E6%8E%A8%E6%B5%81%E6%B5%8B%E8%AF%95

  • 启动
cd /home/test/ZLMediaKit/release/linux/Debug
sudo ./MediaServer -d &
  • 关闭
killall -2 MediaServer
  • 推流
ffmpeg -re -i test.mp4 -vcodec h264 -acodec aac -f rtsp -rtsp_transport tcp rtsp://10.0.20.221/live/test

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【机器学习】信息熵和信息度量

一、说明 信息熵是概率论在信息论的应用,它简洁完整,比统计方法更具有计算优势。在机器学习中经常用到信息熵概念,比如决策树、逻辑回归、EM算法等。本文初略介绍一个皮毛,更多细节等展开继续讨论。 二、关于信息熵的概念 2.1 要素描述 信息熵:熵是一种测量随机变量 X …

深度:全面解析数据智能的金融“炼金术”!

‍数据智能产业创新服务媒体 ——聚焦数智 改变商业 金融以其财富效应&#xff0c;成为最新科技的试金石。一项新技术出来后&#xff0c;人们首先闪过的念头就是“能不能用它赚钱”。例如&#xff0c;ChatGPT带火了大模型&#xff0c;人们也开始将目标聚焦到大模型在金融领域的…

5.1阻塞和非阻塞、同步和异步 5.2Unix、Linux上的五种IO模型

5.1阻塞和非阻塞、同步和异步 典型的一次IO的两个阶段是什么&#xff1f;数据就绪和数据读写 数据就绪&#xff1a;根据IO操作的就绪状态 阻塞非阻塞 数据读写&#xff1a;根据应用程序和内核的交互方式 同步异步 陈硕&#xff1a;在处理IO的时候&#xff0c;阻塞和非阻塞都…

短信压力测试系统,支持自定义接口

短信压力测试系统,支持自定义接口 支持卡密充值&#xff0c;短信压力测试系统&#xff0c;解决一切骚扰电话&#xff0c;教程在压缩包里面 可多个服务器挂脚本分担压力&#xff0c;套了cdn导致无法正常执行脚本可以尝试添加白名单 这边建议使用MySQL方式 同服务器下直接配置…

计算机网络——物理层

物理层 物理层是计算机网络体系结构中的底层层级&#xff0c;负责处理计算机与物理传输媒介之间的接口和通信细节。它主要关注如何在物理媒介上传输原始比特流&#xff0c;并确保数据能够可靠地从发送方传输到接收方。 物理层的主要任务包括&#xff1a; 传输介质&#xff1a…

计算机启动

按下主机上的 power 键后&#xff0c;第一个运行的软件是 BIOS,BIOS 全称叫 Base Input & Output System&#xff0c;即基本输入输出系统。 &#xff08;8086的1MB内存&#xff09; 地址 0&#xff5e;0x9FFFF 处是 DRAM&#xff0c;顶部的 0xF0000&#xff5e;0xFFFFF&am…

【一起啃书】《机器学习》第十章 降维与度量学习

文章目录 第十章 降维与度量学习10.1 k k k近邻学习10.2 低维嵌入10.3 主成分分析10.3.1 定义与步骤10.3.2 最近重构性与最大可分性 10.4 核化线性降维10.5 流形学习10.6 度量学习 第十章 降维与度量学习 10.1 k k k近邻学习 k k k近邻学习是一种常用的监督学习方法&#xf…

基于 unity 配置 adb

1.打开环境变量配置path的环境 2 找到自己的unity安装目录,找到对应路径 配置到 path 属性中 C:\~\Editor\2021.3.0f1c1\Editor\Data\PlaybackEngines\AndroidPlayer\SDK\platform-tools 3 应用保存即可

FPGA中ROM初始化方法

一 读取txt数据文件进行初始化 parameter INIT_FILE "文件路径/Data.txt" &#xff08;**注意文件路径中斜杠方向**&#xff09; reg [DATA_WITDH - 1:0] ROM [DATA_DEPTH - 1:0];initial begin$readmemh(INIT_FILE, ROM, 0, DATA_DEPTH - 1); end Dat…

Java面试题大全(23年整理版)最新全面技巧讲解

程序员面试背八股&#xff0c;可以说是现在互联网开发岗招聘不可逆的形式了&#xff0c;其中最卷的当属 Java&#xff01;&#xff08;网上动不动就是成千上百道的面试题总结&#xff09;你要是都能啃下来&#xff0c;平时技术不是太差的话&#xff0c;面试基本上问题就不会太大…

Loadrunner怎么实现MD5加密

目录 前言&#xff1a; 1、写一个md5.h文件&#xff0c;将其放入脚本路径下 2、在globals.h中加入#include “md5.h” 3、在Action中写脚本&#xff0c;脚本示例如下&#xff1a; 前言&#xff1a; 在 LoadRunner 中实现 MD5 加密可以通过使用 LoadRunner 提供的函数来完成…

使用Python+Flask+HTML写一个测试小工具

背景&#xff1a; 由于公司安全规范限制&#xff0c;我司的测试、预发布、灰度、生产环境&#xff0c;接口间的数据通信通常是加密处理的&#xff0c;给我们日常定位缺陷带来了一定的阻碍&#xff0c;因此我决定使用Python写一个工具&#xff0c;将加密数据转换为正常数据&…

界面开发框架Qt新手入门教程:如何使用Calendar组件创建日历(二)

Qt 是目前最先进、最完整的跨平台C开发工具。它不仅完全实现了一次编写&#xff0c;所有平台无差别运行&#xff0c;更提供了几乎所有开发过程中需要用到的工具。如今&#xff0c;Qt已被运用于超过70个行业、数千家企业&#xff0c;支持数百万设备及应用。 本文中的CalendarWi…

Python3 实例(三) | 菜鸟教程(二十一)

目录 一、Python 二分查找 二、Python 线性查找 三、Python 插入排序 四、Python 快速排序 五、Python 选择排序 六、Python 冒泡排序 七、Python 归并排序 一、Python 二分查找 &#xff08;一&#xff09;二分搜索是一种在有序数组中查找某一特定元素的搜索算法。 &a…

Java8 Stream详解

Stream类继承关系 前置知识 Spliterator接口使用 Spliterator是在java 8引入的一个接口&#xff0c;它通常和stream一起使用&#xff0c;用来遍历和分割序列。 只要用到stream的地方都需要Spliterator&#xff0c;比如List&#xff0c;Collection&#xff0c;IO channel等等…

数据库监控与调优【十七】—— 表结构设计优化

表结构设计优化 第一范式&#xff08;1NF&#xff09; 字段具有原子性&#xff0c;即数据库的每一个字段都是不可分割的原子数据项&#xff0c;不能是集合、数组、记录等非原子数据项 当实体中的某个属性有多个值时&#xff0c;必须拆分为不同的属性 例子&#xff1a; 如图…

《黑马头条》SpringBoot+SpringCloud+ Nacos等企业级微服务架构项目

环境搭建、SpringCloud微服务(注册发现、服务调用、网关) 1)课程对比 2)项目概述 2.1)能让你收获什么 2.2)项目课程大纲 2.3)项目概述 随着智能手机的普及&#xff0c;人们更加习惯于通过手机来看新闻。由于生活节奏的加快&#xff0c;很多人只能利用碎片时间来获取信息&#x…

iview切换Select时选项丢失,重置Seletc时选项丢失

分析原因 在旧版本的iview中如果和filterable一起使用时&#xff0c;当值清空选项或者使用重置按钮清空时选项会丢失。 解决方式一 把去掉filterable 解决方式二 使用ref&#xff0c;调用clearSingleSelect()方法清空 ref"perfSelect" this.$refs.perfSelect.c…

【数据库原理与实践】知识点归纳(下)

第6章 规范化理论 一、关系模式设计中存在的问题 关系、关系模式、关系数据库、关系数据库的模式 关系模式看作三元组&#xff1a;R < U,F >&#xff0c;当且仅当U上的一个关系r满足F时&#xff0c;r称为关系模式R < U,F >的一个关系 第一范式&#xff08;1NF&…

Mybatis-Plus:实现自定义SQL

目录 1.简介 2.自定义SQL具体实现 2.1.注解SQL 2.2.Wrapper传参注解SQL 2.3.Wrapper传参xml文件SQL 2.4.正常传参XML文件SQL 3.总结 1.简介 Mybatis-Plus&#xff08;以下简称MBP&#xff09;的初衷是为了简化开发&#xff0c;而不建议开发者自己写SQL语句的&#xff1b…