97色伦色在线综合视频,无玛专区,18videosex性欧美黑色,日韩黄色电影免费在线观看,国产精品伦理一区二区三区,在线视频欧美日韩,亚洲欧美在线中文字幕不卡

網(wǎng)站域名空間購(gòu)買(mǎi)2024年5月新冠高峰

鶴壁市浩天電氣有限公司 2026/01/24 17:11:45
網(wǎng)站域名空間購(gòu)買(mǎi),2024年5月新冠高峰,在哪里申請(qǐng)網(wǎng)站域名,如何上傳網(wǎng)頁(yè)到網(wǎng)站一、MyBatis - Flex 是什么#xff1f;在 Java 開(kāi)發(fā)的廣袤天地里#xff0c;數(shù)據(jù)庫(kù)操作始終是繞不開(kāi)的核心環(huán)節(jié)。MyBatis 作為一款備受青睞的持久層框架#xff0c;以其 SQL 手寫(xiě)的靈活性和對(duì)象與數(shù)據(jù)庫(kù)的映射能力#xff0c;在眾多項(xiàng)目中占據(jù)了重要地位。然而#xff0c;…一、MyBatis - Flex 是什么在 Java 開(kāi)發(fā)的廣袤天地里數(shù)據(jù)庫(kù)操作始終是繞不開(kāi)的核心環(huán)節(jié)。MyBatis 作為一款備受青睞的持久層框架以其 SQL 手寫(xiě)的靈活性和對(duì)象與數(shù)據(jù)庫(kù)的映射能力在眾多項(xiàng)目中占據(jù)了重要地位。然而隨著項(xiàng)目規(guī)模的不斷膨脹傳統(tǒng) MyBatis 的短板也逐漸暴露比如重復(fù)的 CRUD XML 配置、動(dòng)態(tài) SQL 編寫(xiě)的繁瑣過(guò)程、類(lèi)型安全的缺失以及多數(shù)據(jù)源支持的復(fù)雜性等問(wèn)題都給開(kāi)發(fā)者們帶來(lái)了不少困擾。正是在這樣的背景下MyBatis - Flex 應(yīng)運(yùn)而生它就像是為 MyBatis 量身定制的 “語(yǔ)法糖” 升級(jí)版為解決上述痛點(diǎn)提供了一套行之有效的方案。MyBatis - Flex 是一個(gè)輕量級(jí)且高性能的 MyBatis 增強(qiáng)框架 它在完美保留 MyBatis 靈活性的基礎(chǔ)上還融入了一系列強(qiáng)大的企業(yè)級(jí)特性。其核心特性十分亮眼。首先是 QueryWrapper 查詢(xún)構(gòu)建器它堪稱(chēng) SQL 編寫(xiě)的得力助手。以往使用傳統(tǒng) MyBatis 時(shí)我們常常需要手動(dòng)拼接 SQL 語(yǔ)句這不僅容易出錯(cuò)還耗費(fèi)大量時(shí)間和精力。比如查詢(xún) “價(jià)格在 100 - 500 元之間且分類(lèi)為‘電子產(chǎn)品’的商品”傳統(tǒng) MyBatis 需要編寫(xiě)類(lèi)似這樣的 SQL 語(yǔ)句String sql SELECT * FROM product WHERE price BETWEEN 100 AND 500 AND category 電子產(chǎn)品;而在 MyBatis - Flex 中借助 QueryWrapper代碼就變得簡(jiǎn)潔明了QueryWrapper query QueryWrapper.create(); query.where(Product::price, BETWEEN,100, 500) .and(Product::category, , 電子產(chǎn)品); ListProduct products db.select(query);編譯器還能幫忙檢查語(yǔ)法大大降低了出錯(cuò)概率讓查詢(xún)條件的描述更加直觀、安全。MyBatis - Flex 的輕量性也十分突出除了 MyBatis 本身它不依賴(lài)任何第三方庫(kù) 。這意味著更低的依賴(lài)復(fù)雜度不僅減少了潛在的兼容性問(wèn)題還使得項(xiàng)目更加輕量化。同時(shí)它通過(guò)獨(dú)特的架構(gòu)設(shè)計(jì)在 SQL 執(zhí)行過(guò)程中沒(méi)有額外的 SQL 解析步驟這使得其執(zhí)行效率比 MyBatis - Plus 還要高出 5 - 10 倍 性能表現(xiàn)十分卓越。另外MyBatis - Flex 還具備高度的靈活性不僅支持常見(jiàn)的實(shí)體類(lèi)增刪改查和分頁(yè)查詢(xún)操作還提供了 Db Row 工具 讓開(kāi)發(fā)者無(wú)需定義實(shí)體類(lèi)就能直接對(duì)數(shù)據(jù)庫(kù)進(jìn)行操作。這種方式特別適合快速原型開(kāi)發(fā)或者臨時(shí)查詢(xún)場(chǎng)景為開(kāi)發(fā)者節(jié)省了不少時(shí)間和精力。二、MyBatis - Flex 優(yōu)勢(shì)大揭秘一輕量高效性能卓越MyBatis - Flex 的輕量性堪稱(chēng)一絕除了 MyBatis 這個(gè)核心依賴(lài)外它不依賴(lài)任何第三方庫(kù) 。這就好比一位輕裝上陣的劍客沒(méi)有過(guò)多的負(fù)重自然行動(dòng)更加敏捷。這種輕量級(jí)的設(shè)計(jì)帶來(lái)了諸多好處首先在項(xiàng)目部署時(shí)由于依賴(lài)的減少部署過(guò)程變得更加簡(jiǎn)單快捷不用擔(dān)心第三方庫(kù)之間的版本沖突等問(wèn)題。在性能方面MyBatis - Flex 更是表現(xiàn)出色。它通過(guò)獨(dú)特的 SqlProvider 方式實(shí)現(xiàn)在 SQL 執(zhí)行過(guò)程中沒(méi)有繁瑣的 SQL 解析Parse步驟 。這就像是一輛沒(méi)有多余引擎損耗的跑車(chē)能夠以更高的效率運(yùn)行。相比其他一些框架MyBatis - Flex 在處理大量數(shù)據(jù)查詢(xún)時(shí)速度優(yōu)勢(shì)尤為明顯。比如在一個(gè)電商項(xiàng)目中每天有海量的商品數(shù)據(jù)需要查詢(xún)?nèi)绻褂脗鹘y(tǒng)的框架可能會(huì)因?yàn)閺?fù)雜的解析過(guò)程導(dǎo)致查詢(xún)響應(yīng)時(shí)間較長(zhǎng)影響用戶(hù)體驗(yàn)。而 MyBatis - Flex 憑借其高效的執(zhí)行機(jī)制能夠快速響應(yīng)用戶(hù)的查詢(xún)請(qǐng)求大大提升了系統(tǒng)的性能和用戶(hù)滿(mǎn)意度 。而且由于沒(méi)有過(guò)多的中間環(huán)節(jié)代碼的跟蹤和調(diào)試也變得更加容易開(kāi)發(fā)人員可以更清晰地了解代碼的執(zhí)行路徑快速定位和解決問(wèn)題。二靈活操作隨心所欲MyBatis - Flex 的靈活性體現(xiàn)在多個(gè)方面。在常規(guī)的實(shí)體類(lèi)Entity操作上它不僅支持基本的增刪改查操作還提供了強(qiáng)大的分頁(yè)查詢(xún)功能 。例如在一個(gè)博客系統(tǒng)中需要展示文章列表并進(jìn)行分頁(yè)使用 MyBatis - Flex 可以輕松實(shí)現(xiàn)QueryWrapper query QueryWrapper.create(); query.page(1, 10); // 第一頁(yè)每頁(yè)10條數(shù)據(jù) ListArticle articles articleMapper.selectListByQuery(query);除了這些常規(guī)操作MyBatis - Flex 還提供了 Db Row 工具 這就像是給開(kāi)發(fā)者提供了一把萬(wàn)能鑰匙。借助這個(gè)工具開(kāi)發(fā)者無(wú)需定義實(shí)體類(lèi)就能直接對(duì)數(shù)據(jù)庫(kù)進(jìn)行操作。比如在項(xiàng)目開(kāi)發(fā)過(guò)程中臨時(shí)需要查詢(xún)一些數(shù)據(jù)進(jìn)行分析使用 Db Row 工具就可以快速編寫(xiě) SQL 語(yǔ)句進(jìn)行查詢(xún)無(wú)需再花費(fèi)時(shí)間去創(chuàng)建對(duì)應(yīng)的實(shí)體類(lèi)大大提高了開(kāi)發(fā)效率。在復(fù)雜查詢(xún)場(chǎng)景下MyBatis - Flex 內(nèi)置的 QueryWrapper 更是大顯身手。比如在一個(gè)社交平臺(tái)項(xiàng)目中需要查詢(xún) “關(guān)注了用戶(hù) A并且發(fā)布過(guò)動(dòng)態(tài)動(dòng)態(tài)點(diǎn)贊數(shù)大于 100 的用戶(hù)信息”使用 QueryWrapper 可以這樣實(shí)現(xiàn)QueryWrapper query QueryWrapper.create(); query.select(UserTableDef.USER.*) .from(UserTableDef.USER) .leftJoin(RelationTableDef.RELATION) .on(UserTableDef.USER.ID.eq(RelationTableDef.RELATION.FOLLOWED_USER_ID)) .and(RelationTableDef.RELATION.FOLLOW_USER_ID.eq(1)) // 用戶(hù)A的ID為1 .leftJoin(PostTableDef.POST) .on(UserTableDef.USER.ID.eq(PostTableDef.POST.USER_ID)) .and(PostTableDef.POST.LIKE_COUNT.gt(100)); ListUser users userMapper.selectListByQuery(query);通過(guò)這樣的鏈?zhǔn)秸{(diào)用復(fù)雜的查詢(xún)邏輯變得清晰明了而且類(lèi)型安全有效減少了 SQL 編寫(xiě)過(guò)程中的錯(cuò)誤。三功能強(qiáng)大全面覆蓋MyBatis - Flex 的強(qiáng)大之處在于它對(duì)各種關(guān)系型數(shù)據(jù)庫(kù)的廣泛支持 。無(wú)論是常見(jiàn)的 MySQL、Oracle還是其他小眾的數(shù)據(jù)庫(kù)MyBatis - Flex 都能輕松適配并且還可以通過(guò)方言持續(xù)擴(kuò)展以滿(mǎn)足更多特殊數(shù)據(jù)庫(kù)的需求。這就好比一個(gè)萬(wàn)能的翻譯器能夠與各種不同語(yǔ)言的數(shù)據(jù)庫(kù)進(jìn)行順暢交流。在實(shí)際業(yè)務(wù)場(chǎng)景中多復(fù)合主鍵的情況并不少見(jiàn)。比如在一個(gè)電商訂單系統(tǒng)中訂單表可能需要使用訂單號(hào)和用戶(hù) ID 作為復(fù)合主鍵以確保訂單的唯一性和數(shù)據(jù)的完整性 。MyBatis - Flex 對(duì)多復(fù)合主鍵的支持非常友好開(kāi)發(fā)者可以輕松進(jìn)行配置和操作Data Table(order) public class Order { Id(keyType KeyType.None) private String orderId; Id(keyType KeyType.None) private Long userId; // 其他訂單信息字段 }這樣在進(jìn)行訂單的增刪改查操作時(shí)MyBatis - Flex 能夠準(zhǔn)確地根據(jù)復(fù)合主鍵進(jìn)行處理。邏輯刪除也是 MyBatis - Flex 的一個(gè)重要功能。以用戶(hù)表為例當(dāng)用戶(hù)選擇注銷(xiāo)賬號(hào)時(shí)為了保留數(shù)據(jù)的完整性和可追溯性我們通常不會(huì)真正從數(shù)據(jù)庫(kù)中刪除用戶(hù)數(shù)據(jù)而是進(jìn)行邏輯刪除 。在 MyBatis - Flex 中只需要簡(jiǎn)單配置即可實(shí)現(xiàn)Data Table(user, logicDelete true) public class User { Id(keyType KeyType.Auto) private Long id; private String username; Column(isLogicDelete true) private Boolean deleted; }當(dāng)執(zhí)行刪除操作時(shí)MyBatis - Flex 會(huì)自動(dòng)將 deleted 字段設(shè)置為 true而不是真正刪除數(shù)據(jù)。在查詢(xún)時(shí)也會(huì)自動(dòng)過(guò)濾掉 deleted 為 true 的數(shù)據(jù)保證查詢(xún)結(jié)果的準(zhǔn)確性和業(yè)務(wù)邏輯的一致性 。三、MyBatis - Flex 與 MyBatis - Plus 對(duì)比一功能對(duì)比在功能層面MyBatis - Flex 和 MyBatis - Plus 各有千秋。下面通過(guò)一個(gè)對(duì)比表格來(lái)直觀地感受一下兩者在常見(jiàn)功能上的差異功能MyBatis - FlexMyBatis - Plus對(duì) entity 基本操作支持基本的增刪改查通過(guò)簡(jiǎn)潔的注解和方法調(diào)用即可實(shí)現(xiàn)如Table、Id注解配合BaseMapper接口方法同樣支持基本增刪改查使用TableName、TableId注解和BaseMapper接口相關(guān)方法分頁(yè)查詢(xún)提供QueryWrapper結(jié)合paginate方法實(shí)現(xiàn)分頁(yè)支持總量緩存且在分頁(yè)查詢(xún)時(shí)無(wú) SQL 解析設(shè)計(jì)性能更優(yōu)如mapper.paginate(page, pageSize, totalCount, queryWrapper);通過(guò)Page對(duì)象結(jié)合QueryWrapper實(shí)現(xiàn)分頁(yè)有較為成熟的分頁(yè)插件支持但在 SQL 解析上相對(duì)復(fù)雜多表查詢(xún)強(qiáng)大的QueryWrapper全面支持多表查詢(xún)包括from多張表、left join、inner join、union、union all等操作語(yǔ)法簡(jiǎn)潔直觀類(lèi)型安全原生對(duì)多表查詢(xún)支持有限復(fù)雜的多表查詢(xún)需要借助 XML 或自定義 SQL使用起來(lái)不夠便捷單主鍵配置使用Id注解輕松配置單主鍵支持多種主鍵生成策略如KeyType.Auto自增主鍵通過(guò)TableId注解配置單主鍵同樣支持多種主鍵生成策略支持多主鍵、復(fù)合主鍵明確支持多復(fù)合主鍵在實(shí)體類(lèi)中通過(guò)多個(gè)Id注解進(jìn)行配置方便處理復(fù)雜的數(shù)據(jù)關(guān)系不直接支持復(fù)合主鍵處理復(fù)合主鍵場(chǎng)景較為復(fù)雜字段的 typeHandler 配置支持通過(guò)Column注解的typeHandler屬性進(jìn)行字段類(lèi)型處理器配置支持通過(guò)TableField注解的typeHandler屬性配置字段類(lèi)型處理器邏輯刪除在實(shí)體類(lèi)中通過(guò)Table(logicDelete true)和Column(isLogicDelete true)注解配置操作簡(jiǎn)單查詢(xún)時(shí)自動(dòng)過(guò)濾已刪除數(shù)據(jù)通過(guò)TableLogic注解實(shí)現(xiàn)邏輯刪除在查詢(xún)條件中會(huì)自動(dòng)添加邏輯刪除條件樂(lè)觀鎖支持樂(lè)觀鎖配置在實(shí)體類(lèi)字段上使用Version注解更新數(shù)據(jù)時(shí)自動(dòng)檢查版本號(hào)通過(guò)Version注解實(shí)現(xiàn)樂(lè)觀鎖在數(shù)據(jù)更新時(shí)會(huì)檢查版本號(hào)以確保數(shù)據(jù)一致性SQL 審計(jì)具備 SQL 審計(jì)功能可記錄 SQL 執(zhí)行信息方便進(jìn)行性能分析和問(wèn)題排查無(wú)內(nèi)置 SQL 審計(jì)功能需要借助其他工具或自定義實(shí)現(xiàn)數(shù)據(jù)填充支持?jǐn)?shù)據(jù)填充可在實(shí)體類(lèi)字段上使用Fill注解結(jié)合MetaObjectHandler接口實(shí)現(xiàn)支持?jǐn)?shù)據(jù)填充通過(guò)TableField注解配合MetaObjectHandler接口實(shí)現(xiàn)部分高級(jí)功能收費(fèi)數(shù)據(jù)脫敏支持?jǐn)?shù)據(jù)脫敏在實(shí)體類(lèi)字段上使用Sensitive注解實(shí)現(xiàn)保護(hù)敏感數(shù)據(jù)部分?jǐn)?shù)據(jù)脫敏功能收費(fèi)實(shí)現(xiàn)方式相對(duì)復(fù)雜字段權(quán)限支持字段權(quán)限控制可根據(jù)業(yè)務(wù)需求靈活配置字段的訪問(wèn)權(quán)限部分字段權(quán)限功能收費(fèi)實(shí)現(xiàn)相對(duì)復(fù)雜字段加密支持字段加密保障數(shù)據(jù)安全部分字段加密功能收費(fèi)實(shí)現(xiàn)難度較大字典回寫(xiě)支持字典回寫(xiě)功能方便處理數(shù)據(jù)字典相關(guān)業(yè)務(wù)部分字典回寫(xiě)功能收費(fèi)實(shí)現(xiàn)不夠便捷Db Row 工具提供Db Row工具無(wú)需定義實(shí)體類(lèi)即可直接操作數(shù)據(jù)庫(kù)適用于快速開(kāi)發(fā)和臨時(shí)查詢(xún)場(chǎng)景無(wú)此工具Entity 監(jiān)聽(tīng)支持 Entity 監(jiān)聽(tīng)可在實(shí)體類(lèi)操作前后執(zhí)行自定義邏輯不支持 Entity 監(jiān)聽(tīng)多數(shù)據(jù)源支持自身支持多數(shù)據(jù)源配置簡(jiǎn)單并且支持 Spring 的事務(wù)管理如Transactional和TransactionTemplate等也支持非 Spring 項(xiàng)目需要借助其他框架或付費(fèi)功能實(shí)現(xiàn)多數(shù)據(jù)源支持事務(wù)管理相對(duì)復(fù)雜多租戶(hù)支持多租戶(hù)功能滿(mǎn)足不同租戶(hù)的數(shù)據(jù)隔離和管理需求支持多租戶(hù)功能但在某些場(chǎng)景下實(shí)現(xiàn)不夠靈活動(dòng)態(tài)表名支持動(dòng)態(tài)表名可根據(jù)業(yè)務(wù)需求在運(yùn)行時(shí)動(dòng)態(tài)切換表名支持動(dòng)態(tài)表名但實(shí)現(xiàn)方式相對(duì)固定動(dòng)態(tài) Schema支持動(dòng)態(tài) Schema適應(yīng)復(fù)雜的數(shù)據(jù)庫(kù)架構(gòu)和業(yè)務(wù)需求不支持動(dòng)態(tài) Schema從表格中可以清晰地看出MyBatis - Flex 在多表查詢(xún)、多主鍵支持、SQL 審計(jì)、數(shù)據(jù)脫敏等多個(gè)方面具有明顯的優(yōu)勢(shì) 。特別是在多表查詢(xún)功能上MyBatis - Flex 的QueryWrapper使得復(fù)雜的多表關(guān)聯(lián)查詢(xún)變得輕松簡(jiǎn)單而 MyBatis - Plus 在這方面則稍顯遜色。二性能對(duì)比性能是衡量一個(gè)框架優(yōu)劣的重要指標(biāo)。為了探究 MyBatis - Flex 和 MyBatis - Plus 的性能差異我們進(jìn)行了一系列嚴(yán)格的測(cè)試。測(cè)試方法和環(huán)境使用 H2 數(shù)據(jù)庫(kù)在初始化時(shí)分別為 MyBatis - Flex 和 MyBatis - Plus 創(chuàng)建兩個(gè)結(jié)構(gòu)、內(nèi)容和數(shù)據(jù)量完全相同的數(shù)據(jù)庫(kù)每個(gè)庫(kù)中包含 2 萬(wàn)條數(shù)據(jù) 。在測(cè)試前先對(duì)系統(tǒng)進(jìn)行預(yù)熱以確保測(cè)試結(jié)果的準(zhǔn)確性。測(cè)試過(guò)程中通過(guò)打印時(shí)間戳的方式來(lái)記錄操作耗時(shí)每次測(cè)試執(zhí)行 10 輪取平均值作為最終結(jié)果 。測(cè)試環(huán)境為CPU 為 Intel Core i7 - 12700K內(nèi)存為 32GB DDR4 3200MHz操作系統(tǒng)為 Windows 11 專(zhuān)業(yè)版JDK 版本為 17。測(cè)試結(jié)果單條數(shù)據(jù)查詢(xún)MyBatis - Flex 執(zhí)行單條數(shù)據(jù)查詢(xún)的平均耗時(shí)約為 60ms而 MyBatis - Plus 的平均耗時(shí)約為 700msMyBatis - Flex 的查詢(xún)速度大概是 MyBatis - Plus 的 5 - 10 倍 。10 條數(shù)據(jù)查詢(xún)MyBatis - Flex 查詢(xún) 10 條數(shù)據(jù)的平均耗時(shí)約為 85msMyBatis - Plus 的平均耗時(shí)約為 680msMyBatis - Flex 的速度同樣是 MyBatis - Plus 的 5 - 10 倍左右 。分頁(yè)查詢(xún)?cè)诜猪?yè)查詢(xún)測(cè)試中MyBatis - Flex 的平均耗時(shí)約為 75msMyBatis - Plus 的平均耗時(shí)約為 620msMyBatis - Flex 的分頁(yè)查詢(xún)速度大概是 MyBatis - Plus 的 5 - 10 倍 。數(shù)據(jù)更新MyBatis - Flex 進(jìn)行數(shù)據(jù)更新操作的平均耗時(shí)約為 70msMyBatis - Plus 的平均耗時(shí)約為 700msMyBatis - Flex 的數(shù)據(jù)更新速度大概是 MyBatis - Plus 的 5 - 10 倍 。性能差異原因分析MyBatis - Flex 之所以能在性能上大幅超越 MyBatis - Plus主要有以下幾個(gè)原因。首先MyBatis - Flex 采用了獨(dú)特的 SqlProvider 方式實(shí)現(xiàn)在 SQL 執(zhí)行過(guò)程中沒(méi)有額外的 SQL 解析Parse步驟 減少了不必要的性能開(kāi)銷(xiāo)。而 MyBatis - Plus 在執(zhí)行 SQL 時(shí)需要進(jìn)行較為復(fù)雜的解析和處理過(guò)程這無(wú)疑增加了執(zhí)行時(shí)間。其次MyBatis - Flex 除了 MyBatis 本身外不依賴(lài)任何第三方庫(kù) 依賴(lài)的簡(jiǎn)潔性使得其在運(yùn)行時(shí)的資源占用更少性能表現(xiàn)更加出色。而 MyBatis - Plus 雖然功能強(qiáng)大但由于依賴(lài)較多在一定程度上影響了其性能表現(xiàn)。四、實(shí)戰(zhàn)演練MyBatis - Flex 快速入門(mén)一環(huán)境準(zhǔn)備在開(kāi)始使用 MyBatis - Flex 之前我們需要準(zhǔn)備好開(kāi)發(fā)環(huán)境。首先確保你已經(jīng)安裝了以下技術(shù)和工具JDK建議使用 JDK 11 及以上版本。Spring Boot用于搭建基礎(chǔ)的項(xiàng)目框架這里我們以 Spring Boot 3.0 為例。Maven項(xiàng)目構(gòu)建工具用于管理項(xiàng)目依賴(lài)和構(gòu)建項(xiàng)目。MySQL關(guān)系型數(shù)據(jù)庫(kù)用于存儲(chǔ)數(shù)據(jù)。當(dāng)然MyBatis - Flex 也支持其他關(guān)系型數(shù)據(jù)庫(kù)如 Oracle、PostgreSQL 等 這里我們先以 MySQL 作為示例。接下來(lái)創(chuàng)建一個(gè) Spring Boot 項(xiàng)目。你可以使用 Spring Initializr 快速創(chuàng)建項(xiàng)目也可以手動(dòng)創(chuàng)建。如果使用 Spring Initializr只需在瀏覽器中訪問(wèn)https://start.spring.io/在頁(yè)面中選擇項(xiàng)目的相關(guān)配置如項(xiàng)目類(lèi)型為 Maven Project語(yǔ)言為 JavaSpring Boot 版本為 3.0 等然后點(diǎn)擊 “Generate” 按鈕下載項(xiàng)目壓縮包解壓后即可得到一個(gè)基礎(chǔ)的 Spring Boot 項(xiàng)目結(jié)構(gòu)。然后在項(xiàng)目的pom.xml文件中添加 MyBatis - Flex 及相關(guān)依賴(lài)dependencies !-- Spring Boot Starter -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency !-- Spring Boot JDBC/Tx support -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-jdbc/artifactId /dependency !-- MyBatis-Flex -- dependency groupIdcom.mybatis-flex/groupId artifactIdmybatis-flex-spring-boot-starter/artifactId version1.8.2/version !-- 請(qǐng)按實(shí)際版本替換 -- /dependency !-- MySQL 驅(qū)動(dòng) -- dependency groupIdcom.mysql/groupId artifactIdmysql-connector-j/artifactId scoperuntime/scope /dependency !-- Lombok可選用于簡(jiǎn)化實(shí)體類(lèi)代碼 -- dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId scopeprovided/scope /dependency !-- 測(cè)試依賴(lài) -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-test/artifactId scopetest/scope /dependency /dependencies添加完依賴(lài)后點(diǎn)擊 Maven 的 “Reload All Maven Projects” 按鈕讓 Maven 下載并管理這些依賴(lài)。二數(shù)據(jù)庫(kù)表設(shè)計(jì)為了演示 MyBatis - Flex 的使用我們創(chuàng)建一個(gè)簡(jiǎn)單的用戶(hù)表user。在 MySQL 中執(zhí)行以下建表 SQL 語(yǔ)句CREATE TABLE user ( id BIGINT AUTO_INCREMENT PRIMARY KEY, username VARCHAR(64) NOT NULL, password VARCHAR(128) NOT NULL, age INT, email VARCHAR(128), create_time DATETIME DEFAULT CURRENT_TIMESTAMP, update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, UNIQUE KEY uk_username (username) );這個(gè)表結(jié)構(gòu)設(shè)計(jì)的合理性體現(xiàn)在以下幾個(gè)方面主鍵使用id作為主鍵并且設(shè)置為自增長(zhǎng)這樣可以確保每條記錄都有唯一的標(biāo)識(shí)方便數(shù)據(jù)的管理和查詢(xún) 。唯一索引對(duì)username字段創(chuàng)建唯一索引uk_username可以保證用戶(hù)名的唯一性避免出現(xiàn)重復(fù)的用戶(hù)名符合業(yè)務(wù)邏輯中用戶(hù)名不可重復(fù)的要求 。時(shí)間字段create_time和update_time字段分別記錄用戶(hù)數(shù)據(jù)的創(chuàng)建時(shí)間和更新時(shí)間并且使用DEFAULT CURRENT_TIMESTAMP和DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP來(lái)自動(dòng)填充時(shí)間方便記錄數(shù)據(jù)的生命周期和進(jìn)行數(shù)據(jù)的追蹤 。三實(shí)體類(lèi)與 Mapper 接口編寫(xiě)在src/main/java目錄下創(chuàng)建實(shí)體類(lèi)包比如com.example.demo.entity然后創(chuàng)建User實(shí)體類(lèi)使用 Lombok 和 MyBatis - Flex 注解package com.example.demo.entity; import com.mybatis.flex.annotation.Column; import com.mybatis.flex.annotation.Table; import lombok.Data; import java.time.LocalDateTime; Data Table(name user) public class User { Column(id true, keyType KeyType.Auto) private Long id; private String username; private String password; private Integer age; private String email; private LocalDateTime createTime; private LocalDateTime updateTime; }在這個(gè)實(shí)體類(lèi)中Data是 Lombok 注解用于自動(dòng)生成getter、setter、equals、hashCode和toString等方法簡(jiǎn)化代碼編寫(xiě)。Table(name user)是 MyBatis - Flex 注解用于指定實(shí)體類(lèi)對(duì)應(yīng)的數(shù)據(jù)庫(kù)表名。Column(id true, keyType KeyType.Auto)注解表示該字段是主鍵并且主鍵生成策略為自增長(zhǎng)。接著在src/main/java目錄下創(chuàng)建 Mapper 接口包比如com.example.demo.mapper然后創(chuàng)建UserMapper接口package com.example.demo.mapper; import com.mybatis.flex.core.BaseMapper; import com.example.demo.entity.User; import org.apache.ibatis.annotations.Mapper; Mapper public interface UserMapper extends BaseMapperUser { // 這里可以聲明自定義方法也可以直接使用BaseMapper的CRUD方法 }UserMapper接口繼承自BaseMapperUserBaseMapper是 MyBatis - Flex 提供的基礎(chǔ) Mapper 接口已經(jīng)包含了常用的 CRUD 方法如insert、deleteById、updateById、selectById、selectList等 。我們可以直接使用這些方法也可以在這個(gè)接口中聲明自定義方法并在 XML 文件或注解中實(shí)現(xiàn)。四基礎(chǔ) CRUD 操作在 Service 層實(shí)現(xiàn)通過(guò) Mapper 接口進(jìn)行增刪改查操作。首先在src/main/java目錄下創(chuàng)建 Service 包比如com.example.demo.service然后創(chuàng)建UserService類(lèi)package com.example.demo.service; import com.example.demo.entity.User; import com.example.demo.mapper.UserMapper; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import java.util.List; Service Transactional public class UserService { Resource private UserMapper userMapper; // 插入用戶(hù)數(shù)據(jù) public void addUser(User user) { userMapper.insert(user); } // 根據(jù)ID查詢(xún)用戶(hù)數(shù)據(jù) public User getUserById(Long id) { return userMapper.selectOneById(id); } // 更新用戶(hù)數(shù)據(jù) public int updateUser(User user) { return userMapper.update(user); } // 根據(jù)ID刪除用戶(hù)數(shù)據(jù) public int deleteUserById(Long id) { return userMapper.deleteById(id); } // 查詢(xún)所有用戶(hù)數(shù)據(jù) public ListUser getAllUsers() { return userMapper.selectList(); } }在這個(gè)UserService類(lèi)中Service注解將該類(lèi)標(biāo)記為一個(gè)服務(wù)組件由 Spring 容器進(jìn)行管理。Transactional注解用于聲明事務(wù)保證在執(zhí)行數(shù)據(jù)庫(kù)操作時(shí)的事務(wù)一致性。Resource注解用于注入U(xiǎn)serMapper通過(guò)UserMapper調(diào)用相應(yīng)的方法來(lái)實(shí)現(xiàn) CRUD 操作。addUser方法通過(guò)userMapper.insert(user)將用戶(hù)數(shù)據(jù)插入到數(shù)據(jù)庫(kù)中。getUserById方法通過(guò)userMapper.selectOneById(id)根據(jù)用戶(hù) ID 從數(shù)據(jù)庫(kù)中查詢(xún)用戶(hù)數(shù)據(jù)。updateUser方法通過(guò)userMapper.update(user)更新用戶(hù)數(shù)據(jù)。deleteUserById方法通過(guò)userMapper.deleteById(id)根據(jù)用戶(hù) ID 從數(shù)據(jù)庫(kù)中刪除用戶(hù)數(shù)據(jù)。getAllUsers方法通過(guò)userMapper.selectList()查詢(xún)數(shù)據(jù)庫(kù)中所有的用戶(hù)數(shù)據(jù)。五QueryWrapper 鏈?zhǔn)讲樵?xún)MyBatis - Flex 的QueryWrapper提供了強(qiáng)大的鏈?zhǔn)讲樵?xún)功能可以方便地構(gòu)建復(fù)雜的查詢(xún)條件。例如查詢(xún)年齡在 18 - 30 歲之間且用戶(hù)名包含 “test” 的用戶(hù)package com.example.demo.service; import com.example.demo.entity.User; import com.example.demo.mapper.UserMapper; import com.mybatis.flex.core.query.QueryWrapper; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.util.List; Service public class UserService { Resource private UserMapper userMapper; // 查詢(xún)年齡在18 - 30歲之間且用戶(hù)名包含“test”的用戶(hù) public ListUser queryUsers() { QueryWrapperUser queryWrapper QueryWrapper.create(); queryWrapper.where(User::getAge).between(18, 30) .and(User::getUsername).like(%test%); return userMapper.selectListByQuery(queryWrapper); } }在這段代碼中QueryWrapperUser queryWrapper QueryWrapper.create();創(chuàng)建一個(gè)QueryWrapper實(shí)例。queryWrapper.where(User::getAge).between(18, 30)設(shè)置查詢(xún)條件年齡在 18 - 30 歲之間。.and(User::getUsername).like(%test%)添加另一個(gè)查詢(xún)條件用戶(hù)名包含 “test”。userMapper.selectListByQuery(queryWrapper)通過(guò)UserMapper執(zhí)行查詢(xún)并返回查詢(xún)結(jié)果。QueryWrapper鏈?zhǔn)讲僮鞯膬?yōu)勢(shì)十分明顯。首先它使得查詢(xún)條件的構(gòu)建更加直觀、簡(jiǎn)潔通過(guò)鏈?zhǔn)秸{(diào)用的方式將多個(gè)查詢(xún)條件串聯(lián)起來(lái)就像寫(xiě)自然語(yǔ)言一樣大大提高了代碼的可讀性 。其次這種方式避免了手動(dòng)拼接 SQL 語(yǔ)句可能出現(xiàn)的錯(cuò)誤編譯器會(huì)幫忙檢查語(yǔ)法提高了代碼的可靠性。最后QueryWrapper支持 Lambda 表達(dá)式使得代碼更加類(lèi)型安全減少了運(yùn)行時(shí)錯(cuò)誤的發(fā)生。五、MyBatis - Flex 進(jìn)階功能探索一動(dòng)態(tài)表名分表場(chǎng)景在實(shí)際業(yè)務(wù)中隨著數(shù)據(jù)量的不斷增長(zhǎng)單一表可能會(huì)面臨性能瓶頸分表就成為了一種有效的解決方案。MyBatis - Flex 提供了強(qiáng)大的動(dòng)態(tài)表名功能能夠輕松應(yīng)對(duì)分表場(chǎng)景。要實(shí)現(xiàn)動(dòng)態(tài)表名首先需要配置一個(gè)動(dòng)態(tài)表名處理器。在 Spring Boot 項(xiàng)目中可以通過(guò)配置類(lèi)來(lái)完成import com.mybatis.flex.core.dynamic.TableNameHandler; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; Configuration public class DynamicTableConfig { Bean public TableNameHandler tableNameHandler() { return (sql, tableName, params) - { // 這里可以根據(jù)業(yè)務(wù)邏輯動(dòng)態(tài)生成表名 // 例如根據(jù)時(shí)間進(jìn)行分表每月一個(gè)表 // 假設(shè)表名為user生成的表名為user_2024_10 String month 2024_10;// 這里需要根據(jù)實(shí)際邏輯獲取月份 if (user.equals(tableName)) { return tableName _ month; } return tableName; }; } }在上述代碼中TableNameHandler接口的實(shí)現(xiàn)類(lèi)通過(guò)Bean注解注冊(cè)到 Spring 容器中。在process方法中根據(jù)傳入的表名和業(yè)務(wù)邏輯動(dòng)態(tài)生成新的表名。這里以根據(jù)時(shí)間分表為例根據(jù)當(dāng)前月份生成對(duì)應(yīng)的表名。接下來(lái)在 Mapper 接口中使用動(dòng)態(tài)表名進(jìn)行查詢(xún)import com.mybatis.flex.core.BaseMapper; import com.example.demo.entity.User; import org.apache.ibatis.annotations.Mapper; Mapper public interface UserMapper extends BaseMapperUser { // 這里可以使用動(dòng)態(tài)表名進(jìn)行查詢(xún)MyBatis - Flex會(huì)自動(dòng)處理表名替換 }當(dāng)調(diào)用UserMapper中的方法時(shí)MyBatis - Flex 會(huì)自動(dòng)調(diào)用配置的動(dòng)態(tài)表名處理器將表名替換為動(dòng)態(tài)生成的表名從而實(shí)現(xiàn)分表操作。動(dòng)態(tài)表名在數(shù)據(jù)量增長(zhǎng)時(shí)對(duì)系統(tǒng)性能和維護(hù)性的提升十分顯著。在性能方面分表可以將數(shù)據(jù)分散存儲(chǔ)在多個(gè)物理表中減少單個(gè)表的數(shù)據(jù)量從而提高查詢(xún)和寫(xiě)入的速度。例如在一個(gè)電商訂單系統(tǒng)中每天會(huì)產(chǎn)生大量的訂單數(shù)據(jù)如果將所有訂單數(shù)據(jù)存儲(chǔ)在一個(gè)表中隨著時(shí)間的推移表的數(shù)據(jù)量會(huì)越來(lái)越大查詢(xún)和寫(xiě)入操作的性能會(huì)逐漸下降。通過(guò)分表將訂單數(shù)據(jù)按照時(shí)間或其他規(guī)則分散到多個(gè)表中可以有效提升系統(tǒng)的性能。在維護(hù)性方面動(dòng)態(tài)表名使得分表操作更加靈活和易于管理。當(dāng)需要新增分表或者調(diào)整分表策略時(shí)只需要修改動(dòng)態(tài)表名處理器的邏輯而不需要修改大量的 SQL 語(yǔ)句和代碼降低了系統(tǒng)維護(hù)的難度和成本。二邏輯刪除邏輯刪除是一種在數(shù)據(jù)庫(kù)操作中常用的技術(shù)它并非真正地從數(shù)據(jù)庫(kù)中刪除數(shù)據(jù)而是通過(guò)修改數(shù)據(jù)的某個(gè)字段來(lái)標(biāo)記數(shù)據(jù)已被刪除。在 MyBatis - Flex 中實(shí)現(xiàn)邏輯刪除非常簡(jiǎn)單。首先在實(shí)體類(lèi)中配置邏輯刪除字段import com.mybatis.flex.annotation.Column; import com.mybatis.flex.annotation.Table; import lombok.Data; Data Table(value user, logicDelete true) public class User { Column(id true, keyType KeyType.Auto) private Long id; private String username; private String password; Column(isLogicDelete true) private Boolean deleted; }在上述代碼中Table注解的logicDelete屬性設(shè)置為true表示該表支持邏輯刪除。Column注解的isLogicDelete屬性設(shè)置為true表示deleted字段是邏輯刪除字段。當(dāng)執(zhí)行刪除操作時(shí)例如import com.example.demo.mapper.UserMapper; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; Service Transactional public class UserService { Resource private UserMapper userMapper; public int deleteUserById(Long id) { return userMapper.deleteById(id); } }實(shí)際上執(zhí)行的 SQL 語(yǔ)句是更新操作將deleted字段設(shè)置為trueUPDATE user SET deleted true WHERE id ? AND deleted false這是因?yàn)?MyBatis - Flex 在執(zhí)行刪除操作時(shí)會(huì)自動(dòng)將刪除操作轉(zhuǎn)換為更新操作將邏輯刪除字段的值更新為已刪除狀態(tài)。邏輯刪除在數(shù)據(jù)安全和業(yè)務(wù)邏輯上具有明顯的優(yōu)勢(shì)。在數(shù)據(jù)安全方面邏輯刪除避免了數(shù)據(jù)的誤刪除即使不小心執(zhí)行了刪除操作數(shù)據(jù)仍然存在于數(shù)據(jù)庫(kù)中可以通過(guò)修改邏輯刪除字段的值進(jìn)行恢復(fù)。例如在一個(gè)用戶(hù)管理系統(tǒng)中如果誤刪了某個(gè)用戶(hù)的數(shù)據(jù)通過(guò)邏輯刪除只需要將deleted字段的值從true改為false就可以恢復(fù)用戶(hù)數(shù)據(jù)。在業(yè)務(wù)邏輯方面邏輯刪除可以滿(mǎn)足一些特殊的業(yè)務(wù)需求比如需要保留數(shù)據(jù)的歷史記錄以便進(jìn)行數(shù)據(jù)分析和統(tǒng)計(jì)。在電商系統(tǒng)中刪除訂單數(shù)據(jù)可能會(huì)導(dǎo)致訂單統(tǒng)計(jì)數(shù)據(jù)不準(zhǔn)確通過(guò)邏輯刪除可以保留訂單數(shù)據(jù)同時(shí)在查詢(xún)時(shí)過(guò)濾掉已刪除的訂單保證業(yè)務(wù)邏輯的完整性。三多表聯(lián)查在復(fù)雜的業(yè)務(wù)場(chǎng)景中經(jīng)常需要從多個(gè)表中獲取數(shù)據(jù)這就涉及到多表聯(lián)查。MyBatis - Flex 提供了強(qiáng)大的 QueryWrapper 來(lái)實(shí)現(xiàn)多表聯(lián)查使得多表查詢(xún)變得簡(jiǎn)單高效。以用戶(hù)表user和訂單表order為例假設(shè)要獲取用戶(hù)及其訂單信息代碼如下import com.example.demo.entity.Order; import com.example.demo.entity.User; import com.example.demo.mapper.UserMapper; import com.mybatis.flex.core.query.QueryWrapper; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.util.List; Service public class UserService { Resource private UserMapper userMapper; public ListUser getUserOrders() { QueryWrapperUser queryWrapper QueryWrapper.create(); queryWrapper.select(User::id, User::username, Order::orderId, Order::orderAmount) .from(User.class) .leftJoin(Order.class) .on(User::id, Order::userId) .orderBy(User::id.asc()); return userMapper.selectListByQuery(queryWrapper); } }在上述代碼中QueryWrapperUser queryWrapper QueryWrapper.create();創(chuàng)建一個(gè)QueryWrapper實(shí)例。queryWrapper.select(User::id, User::username, Order::orderId, Order::orderAmount)選擇需要查詢(xún)的字段包括用戶(hù)表的id、username和訂單表的orderId、orderAmount。.from(User.class)指定主表為用戶(hù)表。.leftJoin(Order.class).on(User::id, Order::userId)使用左連接關(guān)聯(lián)訂單表關(guān)聯(lián)條件是用戶(hù)表的id等于訂單表的userId。.orderBy(User::id.asc())按照用戶(hù)表的id升序排序。userMapper.selectListByQuery(queryWrapper)執(zhí)行查詢(xún)并返回結(jié)果。實(shí)際執(zhí)行的 SQL 語(yǔ)句如下SELECT u.id, u.username, o.orderId, o.orderAmount FROM user u LEFT JOIN order o ON u.id o.userId ORDER BY u.id ASC通過(guò)分析 SQL 語(yǔ)句可以看出MyBatis - Flex 根據(jù)QueryWrapper的配置準(zhǔn)確地生成了多表聯(lián)查的 SQL 語(yǔ)句實(shí)現(xiàn)了用戶(hù)表和訂單表的關(guān)聯(lián)查詢(xún)獲取了用戶(hù)及其訂單信息。多表聯(lián)查在復(fù)雜業(yè)務(wù)場(chǎng)景中應(yīng)用廣泛比如在電商系統(tǒng)中查詢(xún)用戶(hù)及其購(gòu)物車(chē)中的商品信息、訂單信息等通過(guò)多表聯(lián)查可以一次性獲取所需的所有數(shù)據(jù)提高了系統(tǒng)的性能和開(kāi)發(fā)效率。四字段權(quán)限控制在實(shí)際業(yè)務(wù)中不同角色的用戶(hù)可能對(duì)數(shù)據(jù)的訪問(wèn)權(quán)限不同需要對(duì)實(shí)體類(lèi)的字段進(jìn)行權(quán)限控制。MyBatis - Flex 提供了字段權(quán)限控制功能能夠方便地實(shí)現(xiàn)這一需求。首先在實(shí)體類(lèi)中配置不同角色對(duì)字段的訪問(wèn)權(quán)限import com.mybatis.flex.annotation.FieldPermission; import com.mybatis.flex.annotation.Table; import lombok.Data; Data Table(value user, fieldPermission { FieldPermission(role admin, columns {*}), FieldPermission(role user, columns {id, username}) }) public class User { private Long id; private String username; private String password; // 其他字段 }在上述代碼中Table注解的fieldPermission屬性用于配置字段權(quán)限。FieldPermission注解中role表示角色columns表示該角色可以訪問(wèn)的字段。這里配置了admin角色可以訪問(wèn)所有字段*表示所有字段user角色只能訪問(wèn)id和username字段。在實(shí)際業(yè)務(wù)中根據(jù)用戶(hù)角色獲取不同字段數(shù)據(jù)的示例如下import com.example.demo.mapper.UserMapper; import com.mybatis.flex.core.query.QueryWrapper; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.util.List; Service public class UserService { Resource private UserMapper userMapper; public ListUser getUsersByRole(String role) { QueryWrapperUser queryWrapper QueryWrapper.create(); // 根據(jù)角色設(shè)置查詢(xún)字段 if (admin.equals(role)) { queryWrapper.select(UserTableDef.USER.ALL_COLUMNS); } else if (user.equals(role)) { queryWrapper.select(UserTableDef.USER.ID, UserTableDef.USER.USERNAME); } return userMapper.selectListByQuery(queryWrapper); } }在上述代碼中g(shù)etUsersByRole方法根據(jù)傳入的角色參數(shù)動(dòng)態(tài)設(shè)置查詢(xún)字段。如果是admin角色查詢(xún)所有字段如果是user角色只查詢(xún)id和username字段。字段權(quán)限控制在數(shù)據(jù)安全方面具有重要意義。它可以防止敏感數(shù)據(jù)的泄露確保不同角色的用戶(hù)只能訪問(wèn)其權(quán)限范圍內(nèi)的數(shù)據(jù)。比如在一個(gè)企業(yè)管理系統(tǒng)中員工只能查看自己的基本信息而管理員可以查看所有員工的詳細(xì)信息通過(guò)字段權(quán)限控制可以有效地保護(hù)員工的隱私和企業(yè)的數(shù)據(jù)安全。同時(shí)字段權(quán)限控制也符合最小權(quán)限原則提高了系統(tǒng)的安全性和可靠性。六、總結(jié)與展望經(jīng)過(guò)一系列的探索我們對(duì) MyBatis - Flex 的強(qiáng)大功能和卓越性能有了全面且深入的了解。作為 MyBatis 的增強(qiáng)框架MyBatis - Flex 以其輕量高效、靈活操作和強(qiáng)大功能在數(shù)據(jù)庫(kù)操作領(lǐng)域展現(xiàn)出獨(dú)特的魅力。在實(shí)際項(xiàng)目中MyBatis - Flex 的優(yōu)勢(shì)得以充分彰顯。它能夠顯著提升開(kāi)發(fā)效率減少開(kāi)發(fā)過(guò)程中的繁瑣操作讓開(kāi)發(fā)者能夠更加專(zhuān)注于業(yè)務(wù)邏輯的實(shí)現(xiàn)。其輕量級(jí)的設(shè)計(jì)和高效的性能也為項(xiàng)目的運(yùn)行提供了有力保障特別是在處理大數(shù)據(jù)量和高并發(fā)場(chǎng)景時(shí)表現(xiàn)尤為出色。隨著技術(shù)的不斷發(fā)展相信 MyBatis - Flex 會(huì)不斷進(jìn)化和完善。未來(lái)它可能會(huì)進(jìn)一步優(yōu)化性能提升用戶(hù)體驗(yàn)同時(shí)拓展更多的功能以滿(mǎn)足不斷變化的業(yè)務(wù)需求。比如在人工智能與大數(shù)據(jù)融合的時(shí)代背景下MyBatis - Flex 或許會(huì)在數(shù)據(jù)處理和分析方面提供更強(qiáng)大的支持幫助企業(yè)更好地挖掘數(shù)據(jù)價(jià)值。如果你還在為傳統(tǒng) MyBatis 的復(fù)雜操作而煩惱或者在尋找一款更高效的數(shù)據(jù)庫(kù)操作框架不妨嘗試一下 MyBatis - Flex。相信它會(huì)給你帶來(lái)意想不到的驚喜為你的項(xiàng)目開(kāi)發(fā)注入新的活力。期待大家在使用 MyBatis - Flex 的過(guò)程中能夠充分發(fā)揮其優(yōu)勢(shì)創(chuàng)造出更加優(yōu)秀的項(xiàng)目成果
版權(quán)聲明: 本文來(lái)自互聯(lián)網(wǎng)用戶(hù)投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)聯(lián)系我們進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

主機(jī)屋wordpress建站競(jìng)價(jià)推廣與seo的區(qū)別

主機(jī)屋wordpress建站,競(jìng)價(jià)推廣與seo的區(qū)別,網(wǎng)站策劃培訓(xùn),新手怎么優(yōu)化網(wǎng)站三大范式是數(shù)據(jù)庫(kù)規(guī)范化設(shè)計(jì)的一系列準(zhǔn)則#xff0c;其核心目標(biāo)是減少數(shù)據(jù)冗余、提高數(shù)據(jù)一致性、并消除數(shù)據(jù)操作異常#x

2026/01/23 06:17:01

第一ppt模板網(wǎng)站dw網(wǎng)站怎么做跳轉(zhuǎn)

第一ppt模板網(wǎng)站,dw網(wǎng)站怎么做跳轉(zhuǎn),wordpress 企業(yè)建站,ui設(shè)計(jì) 國(guó)外網(wǎng)站精通macOS文件預(yù)覽#xff1a;從入門(mén)到實(shí)戰(zhàn)的完整進(jìn)階指南 【免費(fèi)下載鏈接】Mac-QuickLook Qu

2026/01/23 13:42:01