一、MyBatis-plus是什麼
MyBatis-plus(簡稱MP)是一個MyBatis的增強工具,在MyBatis的基礎上隻做增強不做改變,為簡化開發、提高效率而生
特性:無侵入、損耗小、強大的CRUD操作,支援Lambda形式調用、支援主鍵自動生成,支援ActiveRecord模式、支援自定義全局通用操作、内置代碼生成器、内置分頁插件、分頁插件支援多種資料庫、内置性能分析插件、内置全局攔截插件。
二、MyBatis-plus的一些注解
1、@TableName 表名注解
注解在類上,指定類和資料庫表的映射關系,實體類的類名和資料庫表名相同時,可以不指定該注解
2、@TableId 主鍵注解
注解在實體類的某一字段上,表示這個字段對應資料庫表的主鍵,當主鍵名為ID時,無須使用該注解顯式指定主鍵,mp會自動關聯,若類的字段名和表的列名不一緻,可用value屬性指定表的列名
3、@TavleField 字段注解(非主鍵)
注解在某一字段上,指定java實體類的字段和資料庫表的列的映射關系,應用于 排除非表字段(若實體類中某個字段,不對應表中的任何列,它隻是用于儲存一些額外的,或組裝後的資料)、字段驗證政策(通過insertStrategy、updateStrategy、whereStrategy屬性進行配置,可以控制在實體對象進行插入、更新、或作為WHERE條件時,對象的字段要如何組裝到sql語句中)、字段填充政策(通過fill屬性指定,字段為空時會進行自動填充)
4、@Version 樂觀鎖注解,标記@Version在字段上
5、@EnumValue 通枚舉類注解(注解在枚舉字段上)
6、@TableLogic 表字段邏輯處理注解(邏輯删除)
7、@KeySequence 序列主鍵政策 oracle
8、@SqlParser 租戶注解,支援method上以及mapper接口上
9、@InterceptorIgnore插件過濾規則
三、條件構造器
MyBatis-Plus通過EntityWrapper(簡稱EW,MP封裝的一個查詢條件構造器)或者Condition(與EW類似)來讓使用者自由的建構查詢條件,簡單便捷,沒有額外的負擔,能夠有效提高開發效率,它主要用于處理sql拼接,排序,實體參數查詢等。
使用的是資料庫字段,不是java屬性
警告:MyBatis-Plus不支援以及不贊成在RPC調用中把Wrapper進行傳輸,Wrapper很重,傳輸Wrapper可以類比你的controller用map接收值,正确的RPC調用姿勢是寫一個DTO進行傳輸,被調用方再根據DTO執行相應的操作
條件構造器主要涉及到3個類,AbstractWrapper,QueryWrapper,UpdateWrapper。
在AbstractWrapper中提供了非常多的方法用于建構WHERE條件,而QueryWrapper針對SELECT語句,提供了select()方法,可自定義需要查詢的列,而updateWrapper針對UPDATE語句,提供了set()方法,用于構造set語句,條件構造器也支援lambda表達式
AbstractWrapper中用于建構sql語句中的WHERE條件的方法進行部分列舉
eq等于=
eg:eq(“name”,“老王”)——>name=‘老王’
ne不等于<>
eg:ne(“name”,“老王”)——>name <>‘老王’
gt大于>
eg:gt(“age”,18)——>age>18
ge大于等于>=
eg:ge(“age”,18)——>age>=18
Condition
條件構造器的諸多方法中,均可以指定一個boolean類型的參數condition,用來決定該條件是否加入最後生成的WHERE語句中
實體對象作為條件
調用構造函數建立一個Wrapper對象時,可以傳入一個實體對象,後續使用這個Wrapper時,會以實體對象中的非空屬性,建構WHERE條件(預設建構等值比對的WHERE條件,這個行為可以通過實體類裡各個字段上的@TableField注解中的condition屬性進行改變)
若希望針對某些屬性,改變等值比對的行為,則可以在實體類中用@TableField注解進行配置
allEq方法傳入一個map,用來做等值比對
當allEq方法傳入的Map中有value為null的元素時,預設會設定為is null
若想忽略map中value為null的元素,可以在調用allEq時,設定參數boolean null2IsNull為false
若想要在執行allEq時,過濾掉Map中的某些元素,可以調用allEq的重載方法
lambda條件構造器
lambda條件構造器,支援lambda表達式,可以不必像普通條件構造器一樣,以字元串形式指定列名,它可以直接以實體類的方法引用來指定列
四、BaseMapper提供的一些方法
1、Insert
2、deleteById(根據主鍵id删除一條記錄)
3、deleteBatchIds(根據主鍵id進行批量删除)
4、deleteByMap(根據Map進行删除,map中的key為列名,value為值,根據列和值進行等值比對)
5、delete(根據條件構造器Wrapper進行删除)
6、selectById(根據主鍵ID進行查找)
7、selectBatchIds(根據主鍵ID進行批量查找)
8、selectByMap(根據map中指定的列名和列值進行等值比對查找)
9、selectMaps(根據Wrapper條件,查詢記錄,将查詢結果封裝為一個Map,Map 的key為結果的列,value為值)
1、隻查部分列,當某個表的列特别多,而select的時候隻需要選取個别列,查詢的結果也沒必要封裝成Java實體類對象時(隻查部分列時,封裝成實體後,實體對象中的很多屬性會是null),則可以用selectMaps,擷取到指定的列後,再自行進行處理即可
2、進行資料統計
10、selectObjs隻會傳回第一個字段(第一列)的值,其他字段會被舍棄
11、selectList(根據條件構造器Wrapper進行查詢)
12、Update(根據實體entity和條件構造器Wrapper進行更新)
13、updateById(根據入參entity的id進行更新,對于entity中非空的屬性,會出現在UPDATE語句的set後面,即entity中非空的屬性,會被更新到資料庫)
14、selectCount查詢滿足條件的總數,使用這個方法,不能調用QueryWrapper的select方法設定要查詢的列了,這個方法會自動添加select count(1)
五、自定義sql
當mp提供的方法還不能滿足需求時,則可以自定義sql
可以使用mp提供的Wrapper條件構造器來自定義SQL
兩種方式:原生MyBatis和MyBatis-plus
原生MyBatis
- 注解方式
在usermapper中添加注解
- xml方式(使用xml時,若xml檔案與mapper接口檔案不在同一目錄下,則需要在application.yml中配置mapper.xml的存放路徑)
要在application.yml中添加MyBatis-plus配置
mapper-locations:classpath:**/mapper.xml
MyBatis-plus
也可以使用mp提供的Wrapper條件構造器,來自定義sql
六、分頁查詢
BassMapper中提供了兩個方法進行分頁查詢,分别是selectPage和selectMapsPage,前者會将查詢的結果封裝成Java實體對象,後者會封裝成Map<String,Object>
七、AR模式
ActiveRecord模式,通過操作實體對象,直接操作資料庫表,與ORM類似
八、邏輯删除
邏輯删除是為了友善資料恢複,和保護資料本身價值的一種方案
mp提供的邏輯删除實作:
隻需要在application.yml中進行邏輯删除的相關配置即可(全局配置)
若要對某些表進行單獨配置,在實體類的對應字段上使用@TableLogic即可(局部配置)
開啟mp的邏輯删除後,會對sql産生如下的影響
INSERT語句:沒有影響
SELECT語句:追加WHERE條件,過濾掉已删除的資料
UPDATE語句:追加WHERE條件,防止更新到已删除的資料
DELETE語句:轉變為UPDATE語句
上述的影響,隻針對mp自動注入的sql生效,如果是自己手動添加的自定義sql,則不會生效。
九、自動填充
表中常常會有“新增時間”,“修改時間”,“操作人”等字段,比較原始的方式,是每次插入或更新時,手動進行設定,mp可以通過配置,對某些字段進行自動填充
1、在實體類中的某些字段上,通過@TableField設定自動填充
2、實作自動填充處理器
十、樂觀鎖插件
當出現并發操作時,需要確定各個使用者對資料的操作不産生沖突,此時需要一種并發控制手段。悲觀鎖的方法是,在對資料庫的一條記錄進行修改時,先直接加鎖(資料庫的鎖機制),鎖定這條資料,然後再進行操作;而樂觀鎖,它先假設不存在沖突情況,而在實際進行資料操作時,再檢查是否沖突
樂觀鎖插件僅支援updateById(id)和update(entity,wrapper)方法
十一、多表查詢
1、MyBatis實作一對一有聯合查詢和嵌套查詢。
- 聯合查詢是幾個表聯合查詢,隻查詢一次,通過在resultMap裡面配置association節點配置一對一的類就可以完成
- 嵌套查詢是先查一個表,根據這個表裡面的結果的外鍵id,去再另外一個表裡面查詢資料,也是通過association配置,但另外一個表的查詢通過SELECT屬性配置
2、MyBatis實作一對多有聯合查詢和嵌套查詢。
- 聯合查詢是幾個表聯合查詢,隻查詢一次,通過在resultMap裡面配置collection節點配置一對多的類就可以完成
- 嵌套查詢是先查一個表,根據這個表裡面的結果的外鍵id,再去另外一個表裡面查詢資料,也是通過配置collection,但另外一個表的查詢通過select節點配置
使用resultType、resultMap處理傳回結果
resulttype:指定傳回值結果的完全限定名,處理多表查詢的結果,多表查詢需要定義vo封裝查詢的結果,隻能用在單表查詢或者定義vo的情況 ,如果是定義vo不能将關聯的資料封裝為需要獲得某個類的對象
使用resultMap:不需要定義vo類,将關聯資料對應的類,作為另外一個類的屬性
第一步:定義resultMap
第二步:引用resultMap
使用resultMap:用來多表關聯的複雜查詢中,通過需要将關聯查詢的資料封裝為某個實體類對象,如果有特殊業務需要或者說明需要将管理資料封裝為實體類的對象,使用resultMap
插入:如何避免多表聯查
一、添加備援字段
所謂備援字段,就是在主要的資訊上,添加上一些輔助的字段(比如搜尋框中的搜尋關鍵字,清單中的清單項等,這些資訊都是由其他主體或業務上來的),用添加列的方式,來替換掉使用left join或inner join的方式擷取資料,實作清單資料或報表資料的展示,這種方式是違背了資料庫三範式的設計的,可能隻是滿足了三範式中的第一範式或者滿足了第一,第二範式,這種方式在實作上,需要在資料錄入的時候,将所需的資訊都得到,并放入到相應的列上。
适用範圍:單體服務,分布式微服務,DDD方式設計的領域服務中心均可,即便是進行了分庫分表,也同樣适用
缺點:資訊錄入時候,需要将要使用到的資訊都獲得到,并将其放入到相應的字段上去,在并發的時候,會存在性能問題
二、小表廣播
在業務開發中,之是以需要進行多表聯查,是因為很多資料是動态可變的,隻是在主表中存入了關聯表的關聯主鍵,在需要進行資料展現的時候,通過關聯主鍵,得到關聯表的資訊,進而進行資料的拼接和處理,最終通過服務的方式展現出來。
這種處理方式,主要是針對主表資料量大,但是關聯表資料量小,并且關聯表的資料變化頻繁的情況下,在分布式的微服務系統中,使用這種方式。
難點是:所謂的小表,其實就是另外一個服務中的副本表,但是這個副本表的資訊要遠遠小于副本的主題表,這樣的情況下,主題表的資訊同步到副本表,就是一個很重要的事情。既要保證資料的準确性,還要保證資料的及時性,對實作有着比較高的要求。
适用範圍:分布式微服務分庫情況下,清單上的資訊需要從其他一個或幾個微服務資料庫中而來
缺點:實施難度大,資料同步要求高
三、建立集中的服務
建立一個專供的微服務,背後有一個專門的資料庫,通過某種同步機制,把各種需要聯合查詢的資訊同步到這個庫,然後這個微服務就專門提供這類聯表查詢,适合實時性要求不高的分析場合。
這種處理方式,主要還是使用sql的方式去解決問題,即使用資料庫引擎去處理資料關聯的事情。
難點是:關聯資料的實時同步,同步的準确性,以及服務的穩定性,對實作有着比較高的要求
适用範圍:分布式微服務分庫情況下,清單上的資訊需要從其他一個或幾個微服務資料庫中而來
缺點:實施難度大,資料同步要求高,關聯性管理梳理
四、基于資料中心
資料中心可以通過各種資料同步工具将關系型資料庫中的資料抽取出來,放到hdf上去,可以根據關聯性存到類sql的hive上,或者是列式資料庫hbase上去,然後再通過API的 方式向外提供資料服務,當然也可以按照關聯關系将資料放入es上去,基于es來提供資料服務。
基于資料中心的這種處理方式,可以比較好的實作資料服務的功能,但是也有它自己的不足,主要展現在實時性上。
難點是:如何保證資料的實施性,如何建立好資料的關聯性,同樣既要保證資料的準确性,還要保證資料的及時性,對實作有着比較高的要求
适用範圍:單體服務,分布式微服務,DDD方式設計的領域服務中心均可
缺點:需要會大資料處理的人才,需要更多的伺服器資源,需要更多的項目投入(時間),需要保證資料的準确性,一緻性,及時性。
實時要求高的場合,上大資料,流處理,同樣也是相關關聯的資料以流的方式進行計算得到你用關系資料庫必須聯表才能得到的資料。
其他的方式,如在記憶體中進行分頁搜尋查詢,使用CQRS方式,或者是其他,總之都可以解決資料聯查,資料顯示的問題
時間工具類:
MyBatis-plus架構,自動生成映射檔案的工具會将MySQL中的datetime類型轉化成java中的LocalDateTime類型
Java中LocalDate、LocalTime、LocalDateTime三個時間工具類的使用介紹:
在jdk8釋出的時候,推出了LocalDate、LocalTime、LocalDateTime三個時間處理類,以此來彌補之前的日期時間類的不足,簡化日期時間的操作,在jdk8之前,處理日期時間的類是Date、calendar,這兩個不是線程安全的
新推出來的這三個類,與MySQL中的 日期時間類型正好對應,如果我們使用的是MySQL資料庫的話,在插入相應字段的時候,都不需要再進行任何的轉化了
LocalDateTime對應datetime
LocalTime對應time
LocalDate對應date
Mapper CRUD接口
隻需要定義好實體類,建立一個接口,繼承mp提供的BaseMapper,即可使用,mp會在MyBatis啟動時,自動解析實體類和表的映射關系,并注入帶有通用CRUD方法的mapper。
selectMaps:隻查部分列,進行資料統計,這個方法會将查詢結果封裝為一個map,map的key為結果的列,value為值
當某個表的列特别多,而select時候隻需要選取個别列時,查詢出的結果也沒必要封裝成java實體類對象時(隻查部分列,封裝成實體後,實體對象中的很多屬性會是null),則可以用selectmap,擷取到指定的列後,再自行進行處理即可
selectObjs隻會傳回第一個字段(第一列)的值,其他字段會被舍棄
selectCount查詢滿足條件的總數,使用這個方法,不能調用QueryWrapper的select方法設定要查詢的列了,這個方法會自動添加select count(1)