MySQL的Geometry數據處理之WKB方案

MySQL的Geometry數據處理之WKT方案:https://blog.csdn.net/qq_42402854/article/details/140134357

MySQL的Geometry數據處理之WKT方案中,介紹WTK方案的優點,也感受到它的繁瑣和缺陷。比如:

  • 需要借助 ST_GeomFromText和 ST_AsText,讓 SQL語句顯得復雜。
select id, ST_AsText(geometry) AS geometry, update_time, create_time from geometry_data
  • 沒有一種GeomFromText方案可以覆蓋所有的Geometry結構,使得類似的SQL要寫多份。比如:ST_GeomFromText不是萬能的。針對"幾何信息集合"(GeometryCollection)則需要使用ST_GeomCollFromText來轉換。
insert into geometry_data(id, geometry, update_time, create_time) values(#{id}, ST_GeomFromText(#{geometry, jdbcType=BLOB, typeHandler=org.example.typehandlers.GeometryTypeWKTHandler}), now(), now())insert into geometry_data(id, geometry, update_time, create_time) values(#{id}, ST_GeomCollFromText(#{geometry, jdbcType=BLOB, typeHandler=org.example.typehandlers.GeometryTypeWKTHandler}), now(), now())
  • 沒有針對LinearRing(一種特殊的LineString)的處理方法。

MySQL的Geometry數據處理之WKB方案,則可以解決上述問題。

WKB全程Well-Known Binary,它是一種二進制存儲幾何信息的方法。

WKT方法,可以用字符串形式表達幾何信息,如POINT (1 -1)。

WKB方法則表達為:0101000000000000000000F03F000000000000F0BF

這段二進制的拆解如下:
在這里插入圖片描述

  1. byte order:可以是0或者1,它表示是大頂堆(0)還是小頂堆(1)存儲。
  2. WKB type:表示幾何類型。值的對應關系如下:
    ○ 1 Point
    ○ 2 LineString
    ○ 3 Polygon
    ○ 4 MultiPoint
    ○ 5 MultiLineString
    ○ 6 MultiPolygon
    ○ 7 GeometryCollection
  3. 剩下的是坐標信息。

雖然這個結構已經很基礎,但是 MySQL的Geometry結構并不是WKB。準確的說,WKB只是 MySQL的Geometry結構中的一部分。它們的差異是,MySQL的Geometry結構是在WKB之前加了4個字節,用于存儲SRID。

在這里插入圖片描述

還有一點需要注意的是,MySQL存儲Geometry數據使用的是小頂堆。所以WKB的Byte order字段值一定是1。 有了這些知識,我們就可以定義WKB類型的TypeHandler了。

一般我們會使用 org.locationtech.jts的 Geometry類來表達幾何信息。

引入依賴:

        <!--Geometry工具庫依賴--><dependency><groupId>org.locationtech.jts</groupId><artifactId>jts-core</artifactId><version>1.19.0</version></dependency>

一、自定義類型處理器

項目中使用 MyBatis-Plus,自定義字段類型處理器來實現MySQL的Geometry數據處理之WKB方案。
MyBatis-Plus字段類型處理器:https://baomidou.com/guides/type-handler/

在 MyBatis 中,類型處理器(TypeHandler)扮演著 JavaType 與 JdbcType 之間轉換的橋梁角色。它們用于在執行 SQL 語句時,將 Java 對象的值設置到 PreparedStatement 中,或者從 ResultSet 或 CallableStatement 中取出值。

1、完整TypeHandler類

@MappedTypes({Geometry.class})
@MappedJdbcTypes(JdbcType.BLOB)
public class GeometryTypeWKBHandler extends BaseTypeHandler<Geometry> {//private static final PrecisionModel PRECISION_MODEL = new PrecisionModel(PrecisionModel.FIXED); // 保留整數private static final PrecisionModel PRECISION_MODEL = new PrecisionModel(PrecisionModel.FLOATING); // 保留小數private static final Map<Integer, GeometryFactory> GEOMETRY_FACTORIES = new ConcurrentHashMap<>();@Overridepublic void setNonNullParameter(PreparedStatement ps, int i, Geometry parameter, JdbcType jdbcType) throws SQLException {byte[] bytes = serializeGeometry(parameter);ps.setBytes(i, bytes);}@Overridepublic Geometry getNullableResult(ResultSet rs, String columnName) throws SQLException {byte[] bytes = rs.getBytes(columnName);try {return deserializeGeometry(bytes);} catch (ParseException e) {throw new SQLException(e);}}@Overridepublic Geometry getNullableResult(ResultSet rs, int columnIndex) throws SQLException {byte[] bytes = rs.getBytes(columnIndex);try {return deserializeGeometry(bytes);} catch (ParseException e) {throw new SQLException(e);}}@Overridepublic Geometry getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {byte[] bytes = cs.getBytes(columnIndex);try {return deserializeGeometry(bytes);} catch (ParseException e) {throw new SQLException(e);}}/*** 序列化** @param geometry* @return*/private byte[] serializeGeometry(Geometry geometry) {int srid = geometry.getSRID();byte[] bytes = new WKBWriter(2, ByteOrderValues.LITTLE_ENDIAN).write(geometry);return ByteBuffer.allocate(bytes.length + 4).order(ByteOrder.LITTLE_ENDIAN).putInt(srid).put(bytes).array();}/*** 反序列化** @param bytes* @return* @throws ParseException*/private static Geometry deserializeGeometry(byte[] bytes) throws ParseException {if (bytes == null) {return null;}ByteBuffer buffer = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN);int srid = buffer.getInt();byte[] geometryBytes = new byte[buffer.remaining()];buffer.get(geometryBytes);GeometryFactory geometryFactory = GEOMETRY_FACTORIES.computeIfAbsent(srid, i -> new GeometryFactory(PRECISION_MODEL, i));WKBReader reader = new WKBReader(geometryFactory);return reader.read(geometryBytes);}}

2、序列化方法

    private byte[] serializeGeometry(Geometry geometry) {int srid = geometry.getSRID();byte[] bytes = new WKBWriter(2, ByteOrderValues.LITTLE_ENDIAN).write(geometry);return ByteBuffer.allocate(bytes.length + 4).order(ByteOrder.LITTLE_ENDIAN).putInt(srid).put(bytes).array();}

這段代碼先從org.locationtech.jts.geom.Geometry中獲取SRID碼;

然后以小頂堆模式,使用WKBWriter將幾何信息保存為WKB的二進制碼。

然后申請比WKB大4個字節的空間,分別填入SRID和WKB。

這樣整個內存結構就匹配Mysql內部的Geometry內存結構了。

3、反序列化方法

    private static Geometry deserializeGeometry(byte[] bytes) throws ParseException {if (bytes == null) {return null;}ByteBuffer buffer = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN);int srid = buffer.getInt();byte[] geometryBytes = new byte[buffer.remaining()];buffer.get(geometryBytes);GeometryFactory geometryFactory = GEOMETRY_FACTORIES.computeIfAbsent(srid, i -> new GeometryFactory(PRECISION_MODEL, i));WKBReader reader = new WKBReader(geometryFactory);return reader.read(geometryBytes);}

這段代碼會將Mysql內部的Geometry內存結構讀出來,轉換成小頂堆模式。

然后獲取SRID,并以此創建GeometryFactory。

剩下的內容就是WKB的內存了,最后使用WKBReader將這段內存轉換成org.locationtech.jts.geom.Geometry。

二、使用自定義類型處理器

在實體類中,通過 @TableField注解指定自定義的類型處理器。

確保 @TableField注解中的屬性配置正確無誤,特別是value屬性是否匹配數據庫的實際字段名,以及
jdbcType是否正確設置為JdbcType.BLOB,因為地理空間數據通常以BLOB形式存儲。

創建表SQL語句:

CREATE TABLE `t_geo_wkb` (`id` bigint NOT NULL AUTO_INCREMENT COMMENT 'ID',`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創建時間',`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改時間',`del_flag` char(1)  DEFAULT '0' COMMENT '刪除標記,0未刪除,1已刪除',`name` varchar(255) DEFAULT NULL COMMENT '名稱',`geo_type` varchar(255) DEFAULT NULL COMMENT 'geo_type',`geo` geometry NOT NULL COMMENT 'geo幾何數據-GCJ02',PRIMARY KEY (`id`),SPATIAL KEY `idx_geo` (`geo`) COMMENT '空間數據索引'
) ENGINE=InnoDB  COMMENT='幾何數據wkb表';

1、DO類

幾何數據使用 org.locationtech.jts.geom.Geometry類型。

@Getter
@Setter
@TableName("t_geo_wkb")
public class GeoWkbDO implements Serializable {private static final long serialVersionUID = 1L;/*** ID*/@TableId(value = "id", type = IdType.AUTO)private Long id;/*** 創建時間*/@TableField("create_time")private LocalDateTime createTime;/*** 修改時間*/@TableField("update_time")private LocalDateTime updateTime;/*** 刪除標記,0未刪除,1已刪除*/@TableField("del_flag")private String delFlag;/*** 名稱*/@TableField("name")private String name;/*** geo_type*/@TableField("geo_type")private String geoType;/*** geo幾何數據-GCJ02*/@TableField(value = "geo", typeHandler = GeometryTypeWKBHandler.class, jdbcType = JdbcType.BLOB)private Geometry geo;}

2、Mapper.xml

在 Mapper文件中指定 typeHandler, jdbcType。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.charge.ws.core.mapper.GeoWkbMapper"><!-- 通用查詢映射結果 --><resultMap id="BaseResultMap" type="com.charge.ws.core.entity.GeoWkbDO"><id column="id" property="id"/><result column="create_time" property="createTime"/><result column="update_time" property="updateTime"/><result column="del_flag" property="delFlag"/><result column="name" property="name"/><result column="geo_type" property="geoType"/><result column="geo" property="geo" typeHandler="com.charge.ws.handler.jts.GeometryTypeWKBHandler"jdbcType="BLOB"/></resultMap><!-- 通用查詢結果列 --><sql id="Base_Column_List">id, create_time, update_time, del_flag, name, geo_type, geo</sql></mapper>

使用了WKB模式,SQL就會寫的很簡潔,而不需要使用ST_GeomFromText和ST_AsText轉來轉去。可以見得WKB模式讓 SQL XML變得簡單。

三、注冊自定義類型處理器

如果使用 @TableField注解指定自定義類型處理器沒有被執行,我們就需要顯式注冊自定義TypeHandler。

即在配置文件或啟動類中 通過 TypeHandlerRegistry注冊自定義的類型處理器。

@Configuration
@MapperScan("com.xxx.mapper")
public class MyBatisPlusConfig {@Autowiredprivate SqlSessionFactory sqlSessionFactory;@Beanpublic void registerCustomTypeHandlers() {sqlSessionFactory.getConfiguration().getTypeHandlerRegistry().register(Geometry.class, // JavaTypeJdbcType.BLOB, // JdbcTypeGeometryTypeWKBHandler.class // 自定義TypeHandler);}}

四、示例測試

1、單元測試

    @Autowiredprivate GeoWkbService geoWkbService;@Autowiredprivate GeoWkbMapper geoWkbMapper;@Testpublic void testListAll() {List<GeoWkbDO> doList = geoWkbService.listAll();System.out.println(doList);}@Testpublic void testInsert1() {// 點GeometryFactory geometryFactory = new GeometryFactory();Geometry point = geometryFactory.createPoint(new Coordinate(108.939645, 34.343205));GeoWkbDO saveDO = new GeoWkbDO();saveDO.setDelFlag(CommonConstants.DELETE_FLAG_NORMAL);saveDO.setName("點");saveDO.setGeoType("1");saveDO.setGeo(point);geoWkbMapper.insert(saveDO);}@Testpublic void testInsert2() {// 點集合GeometryFactory geometryFactory = new GeometryFactory();LineString lineString = geometryFactory.createLineString(new Coordinate[]{new Coordinate(108.939645, 34.343205), new Coordinate(108.939647, 34.343207),new Coordinate(1, 1)});GeoWkbDO saveDO = new GeoWkbDO();saveDO.setDelFlag(CommonConstants.DELETE_FLAG_NORMAL);saveDO.setName("點集合");saveDO.setGeoType("2");saveDO.setGeo(lineString);geoWkbMapper.insert(saveDO);}@Testpublic void testInsert3() {// 線GeometryFactory geometryFactory = new GeometryFactory();LineString lineString = geometryFactory.createLineString(new Coordinate[]{new Coordinate(108.939645, 34.343205), new Coordinate(108.939647, 34.343207),new Coordinate(2, 2), new Coordinate(3, 3)});GeoWkbDO saveDO = new GeoWkbDO();saveDO.setDelFlag(CommonConstants.DELETE_FLAG_NORMAL);saveDO.setName("線");saveDO.setGeoType("3");saveDO.setGeo(lineString);geoWkbMapper.insert(saveDO);}@Testpublic void testInsert4() {// 線集合GeometryFactory geometryFactory = new GeometryFactory();MultiLineString multiLineString = geometryFactory.createMultiLineString(new LineString[]{geometryFactory.createLineString(new Coordinate[]{new Coordinate(108.939645, 34.343205), new Coordinate(108.939647, 34.343207)}),geometryFactory.createLineString(new Coordinate[]{new Coordinate(108.939648, 34.343208), new Coordinate(108.939649, 34.343209)})});GeoWkbDO saveDO = new GeoWkbDO();saveDO.setDelFlag(CommonConstants.DELETE_FLAG_NORMAL);saveDO.setName("線集合");saveDO.setGeoType("4");saveDO.setGeo(multiLineString);geoWkbMapper.insert(saveDO);}@Testpublic void testInsert5() {// 面GeometryFactory geometryFactory = new GeometryFactory();Polygon polygon = geometryFactory.createPolygon(new Coordinate[]{new Coordinate(1, 1),new Coordinate(2, 2), new Coordinate(3, 3), new Coordinate(1, 1)});GeoWkbDO saveDO = new GeoWkbDO();saveDO.setDelFlag(CommonConstants.DELETE_FLAG_NORMAL);saveDO.setName("面");saveDO.setGeoType("5");saveDO.setGeo(polygon);geoWkbMapper.insert(saveDO);}@Testpublic void testInsert6() {// 面集合GeometryFactory geometryFactory = new GeometryFactory();MultiPolygon multiPolygon = geometryFactory.createMultiPolygon(new Polygon[]{geometryFactory.createPolygon(new Coordinate[]{new Coordinate(1, 1), new Coordinate(2, 2),new Coordinate(3, 3), new Coordinate(1, 1)}),geometryFactory.createPolygon(new Coordinate[]{new Coordinate(4, 4), new Coordinate(5, 5),new Coordinate(6, 6), new Coordinate(4, 4)})});GeoWkbDO saveDO = new GeoWkbDO();saveDO.setDelFlag(CommonConstants.DELETE_FLAG_NORMAL);saveDO.setName("面集合");saveDO.setGeoType("6");saveDO.setGeo(multiPolygon);geoWkbMapper.insert(saveDO);}@Testpublic void testInsert7() {// 幾何信息集合GeometryFactory geometryFactory = new GeometryFactory();GeometryCollection geometryCollection = geometryFactory.createGeometryCollection(new Geometry[]{geometryFactory.createPoint(new Coordinate(1, 1)),geometryFactory.createLineString(new Coordinate[]{new Coordinate(1, 1), new Coordinate(2, 2)}),geometryFactory.createPolygon(new Coordinate[]{new Coordinate(1, 1), new Coordinate(2, 2),new Coordinate(3, 3), new Coordinate(1, 1)})});GeoWkbDO saveDO = new GeoWkbDO();saveDO.setDelFlag(CommonConstants.DELETE_FLAG_NORMAL);saveDO.setName("幾何信息集合");saveDO.setGeoType("7");saveDO.setGeo(geometryCollection);geoWkbMapper.insert(saveDO);}@Testpublic void testInsert8() {// 面-點集合GeometryFactory geometryFactory = new GeometryFactory();MultiPoint multiPoint = geometryFactory.createMultiPointFromCoords(new Coordinate[]{new Coordinate(1, 1), new Coordinate(2, 2), new Coordinate(3, 3)});GeoWkbDO saveDO = new GeoWkbDO();saveDO.setDelFlag(CommonConstants.DELETE_FLAG_NORMAL);saveDO.setName("面-點集合");saveDO.setGeoType("8");saveDO.setGeo(multiPoint);geoWkbMapper.insert(saveDO);}@Testpublic void testInsert9() {// linearRingGeometryFactory geometryFactory = new GeometryFactory();LinearRing linearRing = geometryFactory.createLinearRing(new Coordinate[] { new Coordinate(1, 1),new Coordinate(2, 2), new Coordinate(3, 3), new Coordinate(1, 1) });GeoWkbDO saveDO = new GeoWkbDO();saveDO.setDelFlag(CommonConstants.DELETE_FLAG_NORMAL);saveDO.setName("linearRing");saveDO.setGeoType("9");saveDO.setGeo(linearRing);geoWkbMapper.insert(saveDO);}@Testpublic void testUpdateById() {GeometryFactory geometryFactory = new GeometryFactory();Coordinate coordinate = new Coordinate(2, 2);Geometry point = geometryFactory.createPoint(coordinate);GeoWkbDO updateDO = new GeoWkbDO();updateDO.setId(1L);updateDO.setGeo(point);geoWkbMapper.updateById(updateDO);}

在這里插入圖片描述

2、返回VO序列化

因為 DO定義的是 Geometry類型,業務中流轉沒問題,但是我們希望返回的 VO對象的這個字段為字符串格式的內容。所以,我們需要指定字段的序列化器,下面我們自定義序列化器。

(1)自定義序列化器

public class GeometrySerializer extends JsonSerializer<Object> {@Overridepublic void serialize(Object obj, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {if (obj != null) {jsonGenerator.writeString(obj.toString());}}
}

(2)VO對象上添加序列化器

    @ApiModelProperty("geo幾何數據-GCJ02")@JsonSerialize(using = GeometrySerializer.class)private Geometry geo;

在這里插入圖片描述

參考文章:

  • Mysql的Geometry數據處理之WKB方案:https://fangliang.blog.csdn.net/article/details/139097706

— 求知若饑,虛心若愚。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/40662.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/40662.shtml
英文地址,請注明出處:http://en.pswp.cn/web/40662.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Spring @Cacheable緩存注解用法說明

注解Cacheable 是 Spring 框架中用于緩存數據的方法或類的注解。通過使用這個注解&#xff0c;你可以避免重復計算和重復獲取數據&#xff0c;從而提高應用程序的性能。 基本用法 引入依賴 確保在你的項目中引入了 Spring Cache 相關的依賴。如果你使用的是 Spring Boot&…

中英雙語介紹中國的城市:上海市(Shanghai)

中文版 上海市是中國最大的城市之一&#xff0c;也是全球重要的金融、貿易和航運中心。作為一座現代化的國際大都市&#xff0c;上海以其繁華的商業區、豐富的文化遺產和多樣化的經濟結構而聞名。以下是對上海市的詳細介紹&#xff0c;包括其地理位置、人口、經濟、教育、文化…

qt結合vs2022安裝

進入清華大學開源軟件&#xff1a; 清華大學開源軟件鏡像站 | Tsinghua Open Source Mirror 下載完成后&#xff0c;雙擊進行安裝&#xff1a; 進入郵箱進行驗證&#xff1a; 可能是因為網絡問題&#xff0c;無法安裝。 重新安裝5.12.12版本。 安裝后啟動失敗&#xff0c;重新…

后端接口設計考慮要點

1. 接口參數校驗 入參校驗&#xff1a;確保必要參數不為空&#xff0c;限制長度和格式&#xff08;例如郵箱格式&#xff09;。返回值校驗&#xff1a;確定返回值不為空&#xff0c;為空時返回與前端協商的默認值。 2. 接口擴展性 設計通用接口而非僅針對特定業務流程的接口…

橫截面交易策略:概念與示例

數量技術宅團隊在CSDN學院推出了量化投資系列課程 歡迎有興趣系統學習量化投資的同學&#xff0c;點擊下方鏈接報名&#xff1a; 量化投資速成營&#xff08;入門課程&#xff09; Python股票量化投資 Python期貨量化投資 Python數字貨幣量化投資 C語言CTP期貨交易系統開…

數據結構--單鏈表實現

歡迎光顧我的homepage 前言 鏈表和順序表都是線性表的一種&#xff0c;但是順序表在物理結構和邏輯結構上都是連續的&#xff0c;但鏈表在邏輯結構上是連續的&#xff0c;而在物理結構上不一定連續&#xff1b;來看以下圖片來認識鏈表與順序表的差別 這里以動態順序表…

WGAN(Wassertein GAN)

WGAN E x ~ P g [ log ? ( 1 ? D ( x ) ) ] E x ~ P g [ ? log ? D ( x ) ] \begin{aligned} & \mathbb{E}_{x \sim P_g}[\log (1-D(x))] \\ & \mathbb{E}_{x \sim P_g}[-\log D(x)] \end{aligned} ?Ex~Pg??[log(1?D(x))]Ex~Pg??[?logD(x)]? 原始 GAN …

springboot基于Java的超市進銷存系統+ LW+ PPT+源碼+講解

第三章系統分析與設計 3.1 可行性分析 一個完整的系統&#xff0c;可行性分析是必須要有的&#xff0c;因為他關系到系統生存問題&#xff0c;對開發的意義進行分析&#xff0c;能否通過本網站來補充線下超市進銷存管理模式中的缺限&#xff0c;去解決其中的不足等&#xff0c…

6域名系統DNS

《計算機網絡》第7版&#xff0c;謝希仁 每次記不清楚的知識點&#xff0c;通過上網查找&#xff0c;總是只能看到很零碎的答案。最后還是最喜歡看這個版本的書&#xff0c;一看就回憶起來了&#xff0c;邏輯嚴謹&#xff0c;循循善誘&#xff0c;知識講解的全面又清晰&#xf…

架構師應該在團隊中發揮怎樣的作用?

架構師分為5種&#xff1a; 1.企業架構師EA(Enterprise Architect) EA的職責是決定整個公司的技術路線和技術發展方向。 2.基礎結構架構師IA(Infrastructure Architect) IA的工作就是提煉和優化技術方面積累和沉淀形成的基礎性的、公共的、可復用的框架和組件&#xff0c;這…

Qt 基礎組件速學 鼠標和鍵盤事件

學習目標&#xff1a; 鼠標事件和鍵盤事件應用 前置環境 運行環境:qt creator 4.12 學習內容和效果演示&#xff1a; 1.鼠標事件 根據鼠標的坐標位置&#xff0c;做出對應的事件。 2.鍵盤事件 根據鍵盤的輸入做出對應操作 詳細主要代碼 1.鼠標事件 #include "main…

一文讀懂輕量日志收集系統Loki工作原理

Loki 是由 Grafana Labs 開發的日志聚合系統&#xff0c;設計目標是提供一種高效、低成本的日志收集和查詢解決方案。與傳統的日志系統&#xff08;如 ELK Stack&#xff09;不同&#xff0c;Loki 不會對日志內容進行索引&#xff0c;而是僅對日志的元數據進行索引&#xff0c;…

美國大帶寬服務器租用優勢和注意事項

美國大帶寬服務器租用對于需要處理大量數據和提供高速網絡服務的企業至關重要。下面將詳細討論美國大帶寬服務器租用的優勢、適用場景及注意事項&#xff0c;rak部落小編為您整理發布美國大帶寬服務器租用的優勢和注意事項。 優勢 1. 高速數據傳輸&#xff1a; - 大帶寬服務器提…

FTP、http 、tcp

HTTP VS FTP HTTP &#xff1a;HyperText Transfer Protocol 超文本傳輸協議&#xff0c;是基于TCP協議 FTP&#xff1a; File Transfer Protocol 文件傳輸協議&#xff0c; 基于TCP協議&#xff0c; 基于UDP協議的FTP 叫做 TFTP HTTP 協議 通過一個SOCKET連接傳輸依次會話數…

FIND_IN_SET使用案例--[sql語句根據多ids篩選出對應數據]

一 FIND_IN_SET select id,system_ids from intellect_client_info where FIND_IN_SET(5, system_ids) > 0;

Spring Boot 中的監視器是什么?有什么作用?

前言&#xff1a; 監聽器相信熟悉 Spring、Spring Boot 的都知道&#xff0c;但是監視器又是什么&#xff1f;估計很多人一臉懵的狀態&#xff0c;本篇分享一下 Spring Boot 的監視器。 Spring Boot 系列文章傳送門 Spring Boot 啟動流程源碼分析&#xff08;2&#xff09; …

Apache DolphinScheduler 與 AWS 的 EMR/Redshift 集成實踐分享

引言 這篇文章將給大家講解關于DolphinScheduler與AWS的EMR和Redshift的集成實踐&#xff0c;通過本文希望大家能更深入地了解AWS智能湖倉架構&#xff0c;以及DolphinScheduler在實際應用中的重要性。 AWS智能湖倉架構 首先&#xff0c;我們來看一下AWS經典的智能湖倉架構圖…

【第20章】MyBatis-Plus邏輯刪除支持

文章目錄 前言一、邏輯刪除的工作原理二、支持的數據類型三、使用方法1.配置全局邏輯刪除屬性2.在實體類中使用 TableLogic 注解 四、常見問題解答1. 如何處理插入操作&#xff1f;2. 刪除接口自動填充功能失效怎么辦&#xff1f; 五、實戰1. 全局配置2. 添加TableLogic3. 自動…

高考選專業,興趣與就業前景該如何平衡?

從高考結束的那一刻開始&#xff0c;有些家長和學生就已經變得焦慮了&#xff0c;因為他們不知道成績出來的時候學生應該如何填報志愿&#xff0c;也不知道選擇什么樣的專業&#xff0c;畢竟大學里面的專業豐富多彩&#xff0c;如何選擇確實是一門學問&#xff0c;而對于學生們…

Oracle的RECYCLEBIN回收站:輕松恢復誤刪對象

目錄 Oracle的RECYCLEBIN回收站&#xff1a;輕松恢復誤刪對象一、概念二、工作原理三、使用方法1 查看回收站中的對象2 恢復回收站中的對象2.1 恢復表&#xff08;TABLE&#xff09;2.2 恢復索引&#xff08;INDEX&#xff09;2.3 恢復視圖&#xff08;VIEW&#xff09;2.4 恢復…