MyBatis-Plus?ORM數(shù)據(jù)庫和實(shí)體類映射方式
在開發(fā)中,數(shù)據(jù)庫和 Java 對(duì)象的映射(ORM)是一個(gè)繞不開的話題,而 MyBatis-Plus(MP)作為一款優(yōu)秀的 ORM 工具,幫我們簡(jiǎn)化了繁瑣的數(shù)據(jù)庫操作。本文將從數(shù)據(jù)庫基礎(chǔ)、表與實(shí)體映射、復(fù)雜對(duì)象映射、自定義 SQL 等角度,深入探討 MP 的數(shù)據(jù)庫映射功能。
一、數(shù)據(jù)庫設(shè)計(jì)基本知識(shí)
在開始 ORM 映射之前,理解數(shù)據(jù)庫設(shè)計(jì)的基本原則至關(guān)重要:
1. 索引
索引可以提高查詢效率,例如主鍵索引、唯一索引、復(fù)合索引等。
在創(chuàng)建實(shí)體時(shí),可以用注解標(biāo)注需要索引的字段:
@TableField("username")
@TableIndex(type = IndexType.UNIQUE)
private String username;2. 主鍵與外鍵
- 主鍵:標(biāo)識(shí)表中每一行記錄的唯一性。
- 外鍵:用來建立表與表之間的關(guān)系。
3. 范式
數(shù)據(jù)庫范式(如第一范式、第三范式)是設(shè)計(jì)良好表結(jié)構(gòu)的重要參考。
Tip: 保持表結(jié)構(gòu)簡(jiǎn)單,但不妨礙業(yè)務(wù)擴(kuò)展。
二、表與實(shí)體的映射關(guān)系
MP 提供了豐富的注解,幫助開發(fā)者高效完成數(shù)據(jù)庫表與 Java 對(duì)象的映射。
1. 基本映射
MP 默認(rèn)將表名與實(shí)體名直接映射,但我們可以通過注解自定義:
表名映射:使用 @TableName 注解將實(shí)體類與數(shù)據(jù)庫表關(guān)聯(lián):
@TableName("user")
public class User {
@TableId(value = "id", type = IdType.AUTO)
private Long id;
@TableField("username")
private String name;
}字段名映射:數(shù)據(jù)庫字段名通常為下劃線風(fēng)格,Java 屬性名為駝峰風(fēng)格。當(dāng)字段名與屬性名不一致時(shí),MP 默認(rèn)自動(dòng)處理這種映射,也可以通過 @TableField 自定義:
@TableField("email_address")
private String emailAddress;2. 自定義主鍵生成策略
主鍵生成是 ORM 映射中重要的一環(huán),當(dāng)往數(shù)據(jù)庫添加字段的時(shí)候,此id會(huì)根據(jù)指定的主鍵生成策略來進(jìn)行生成對(duì)應(yīng)的值。MP 支持多種主鍵生成策略:
IdType.AUTO:
- 適用于主鍵為自增類型(如 MySQL 的
AUTO_INCREMENT) - 在插入數(shù)據(jù)時(shí),不需要為主鍵賦值,由數(shù)據(jù)庫根據(jù)自增策略生成。
- 此策略僅在數(shù)據(jù)庫支持自增主鍵的情況下有效,需要在數(shù)據(jù)庫中保證主鍵是自增的。
IdType.ASSIGN_ID:
- MyBatis-Plus 默認(rèn)的主鍵生成策略,使用 雪花算法 生成全局唯一 ID。
- 在插入數(shù)據(jù)時(shí),MP 自動(dòng)生成主鍵值,并在 SQL 中直接插入該值。
- 數(shù)據(jù)庫表的主鍵類型為
BIGINT,需要全局唯一標(biāo)識(shí)符。
IdType.INPUT:
- 手動(dòng)輸入主鍵值
- 需要在插入數(shù)據(jù)前手動(dòng)設(shè)置主鍵值,否則插入操作將失敗。
- 適用于特定業(yè)務(wù)場(chǎng)景(如主鍵由外部系統(tǒng)生成)。
示例:
在實(shí)體類中通過注解設(shè)置:
@TableId(value = "id", type = IdType.AUTO) private Long id;
全局設(shè)置主鍵策略(application.yaml 配置文件中)
mybatis-plus:
global-config:
db-config:
id-type: ASSIGN_ID # 全局默認(rèn)使用雪花算法
# 可選值:
# AUTO: 數(shù)據(jù)庫自增
# NONE: 無狀態(tài)
# INPUT: 手動(dòng)輸入
# ASSIGN_ID: 雪花算法
# ASSIGN_UUID: UUID三、XML 中配置復(fù)雜映射
1. 基本數(shù)據(jù)類型映射
對(duì)于普通表字段到實(shí)體屬性的映射,MP 提供了簡(jiǎn)單直觀的方式。
通過 resultMap 解決復(fù)雜結(jié)果集的映射問題。
指定了id之后,如果查詢數(shù)據(jù)中包含了多個(gè)id的值,會(huì)自動(dòng)合并,映射為一個(gè)對(duì)象集合
a. 基本映射規(guī)則
MP 默認(rèn)遵循數(shù)據(jù)庫字段名和實(shí)體類屬性名之間的映射規(guī)則:
- 數(shù)據(jù)庫字段名:下劃線命名。
- Java 屬性名:駝峰命名。
示例表結(jié)構(gòu)(user 表):
CREATE TABLE user (
id BIGINT PRIMARY KEY,
username VARCHAR(50),
age INT
);實(shí)體類定義:
@Data
public class User {
private Long id; // 對(duì)應(yīng)數(shù)據(jù)庫字段 id
private String username; // 對(duì)應(yīng)數(shù)據(jù)庫字段 username
private Integer age; // 對(duì)應(yīng)數(shù)據(jù)庫字段 age
}b. 自定義字段映射
通過 column 屬性來指定表字段
<resultMap id="userMap" type="User">
<id property="id" column="id"/>
<result property="username" column="user_name"/>
<result property="age" column="age"/>
</resultMap>2. 嵌套對(duì)象映射
嵌套對(duì)象映射用于處理對(duì)象屬性本身是另一個(gè)復(fù)雜對(duì)象的場(chǎng)景,例如主表與子表關(guān)聯(lián)。
a. 表和實(shí)體類
假設(shè)有以下表結(jié)構(gòu):
user表:
CREATE TABLE user (
id BIGINT PRIMARY KEY,
name VARCHAR(50)
); address表:
CREATE TABLE address (
id BIGINT PRIMARY KEY,
user_id BIGINT,
city VARCHAR(50),
FOREIGN KEY (user_id) REFERENCES user(id)
);實(shí)體類定義:
@Data
public class User {
private Long id;
private String name;
private Address address; // 嵌套對(duì)象
}
@Data
public class Address {
private Long id;
private Long userId;
private String city;
}b. XML 映射
在 XML 文件中通過 <association> 定義嵌套對(duì)象映射:
<resultMap id="userWithAddressMap" type="User">
<id property="id" column="id"/>
<result property="name" column="name"/>
<association property="address" javaType="Address">
<id property="id" column="address_id"/>
<result property="city" column="city"/>
</association>
</resultMap>
<select id="selectUserWithAddress" resultMap="userWithAddressMap">
SELECT u.id, u.name, a.id AS address_id, a.city
FROM user u
LEFT JOIN address a ON u.id = a.user_id
</select>3. 集合類型映射
當(dāng)查詢結(jié)果中存在一個(gè)字段包含 多個(gè)值(例如多個(gè)標(biāo)簽 tag),并且在實(shí)體類中將該字段指定為 集合類型(如 List<String>),MyBatis-Plus 會(huì)根據(jù)配置自動(dòng)將這些值合并并映射為集合。
這種場(chǎng)景常見于 一對(duì)多 或 多對(duì)多 的查詢中,主要通過 <collection> 元素 實(shí)現(xiàn)。
a. 基本示例
① 假設(shè)有以下數(shù)據(jù):
article_tag表
| article_id | tag |
|---|---|
| 1 | Spring |
| 1 | MyBatis |
| 2 | Java |
② 實(shí)體類定義
public class Article {
private Long id; // 文章 ID
private String title; // 文章標(biāo)題
private List<String> tags; // 標(biāo)簽集合
}③ Mapper 配置(XML 映射文件)
使用 <collection> 將多行數(shù)據(jù)的 tag 字段自動(dòng)映射為一個(gè)集合:
<resultMap id="ArticleResultMap" type="com.example.Article">
<id property="id" column="article_id" />
<result property="title" column="title" />
<collection property="tags" ofType="java.lang.String">
<result column="tag" />
</collection>
</resultMap>
<select id="selectArticlesWithTags" resultMap="ArticleResultMap">
SELECT
a.id AS article_id,
a.title,
t.tag
FROM
article a
LEFT JOIN
article_tag t
ON
a.id = t.article_id
</select>④ 查詢結(jié)果
List<Article> articles = articleMapper.selectArticlesWithTags();
假設(shè)查詢結(jié)果為:
[
{
"id": 1,
"title": "學(xué)習(xí) MyBatis",
"tags": ["Spring", "MyBatis"]
},
{
"id": 2,
"title": "Java 基礎(chǔ)",
"tags": ["Java"]
}
]b. 對(duì)象類型集合
以用戶為例和訂單表為例:
① 表和實(shí)體類
假設(shè)有以下表結(jié)構(gòu):
user表:
CREATE TABLE user (
id BIGINT PRIMARY KEY,
name VARCHAR(50)
);order表:
CREATE TABLE order (
id BIGINT PRIMARY KEY,
user_id BIGINT,
order_number VARCHAR(50),
FOREIGN KEY (user_id) REFERENCES user(id)
);② 實(shí)體類定義:
@Data
public class User {
private Long id;
private String name;
private List<Order> orders; // 集合類型
}
@Data
public class Order {
private Long id;
private Long userId;
private String orderNumber;
}③ XML 映射
在 XML 文件中通過 <collection> 定義集合映射:
<resultMap id="userWithOrdersMap" type="User">
<id property="id" column="id"/>
<result property="name" column="name"/>
<collection property="orders" ofType="Order">
<id property="id" column="order_id"/>
<result property="orderNumber" column="order_number"/>
</collection>
</resultMap>
<select id="selectUserWithOrders" resultMap="userWithOrdersMap">
SELECT u.id, u.name, o.id AS order_id, o.order_number
FROM user u
LEFT JOIN order o ON u.id = o.user_id
</select>【注意事項(xiàng)】
- <collection> 的 ofType 屬性指定集合中元素的類型。
- 確保 SQL 查詢中包含子表數(shù)據(jù),否則集合為空。
四、自定義 SQL
MP 提供了兩種自定義 SQL 的方式:XML 文件和注解方式。
1. 使用注解自定義 SQL
在 Mapper 接口中直接使用注解書寫簡(jiǎn)單 SQL:
@Mapper
public interface UserMapper extends BaseMapper<User> {
@Select("SELECT * FROM user WHERE name = #{name}")
User findByName(@Param("name") String name);
}- 優(yōu)點(diǎn):簡(jiǎn)潔、輕量化。
- 缺點(diǎn):不適合復(fù)雜查詢。
2. 使用 XML 文件自定義 SQL
對(duì)于復(fù)雜 SQL,建議使用 XML 文件。MP 通過 Mapper 文件與 XML 配置綁定:
UserMapper.java
@Mapper
public interface UserMapper extends BaseMapper<User> {
User selectUserWithOrders(Long userId);
}UserMapper.xml
<resultMap id="userResultMap" type="User">
<id property="id" column="id"/>
<result property="name" column="name"/>
<collection property="orders" ofType="Order">
<id property="id" column="order_id"/>
<result property="orderNumber" column="order_number"/>
</collection>
</resultMap>
<mapper namespace="com.example.mapper.UserMapper">
<select id="selectUserWithOrders" resultType="User">
SELECT u.*, o.*
FROM user u
LEFT JOIN order o ON u.id = o.user_id
WHERE u.id = #{userId}
</select>
</mapper>五、寫在最后
總結(jié):
- MP 將實(shí)體類與數(shù)據(jù)庫表映射打通,使得開發(fā)效率提升。
- 對(duì)于復(fù)雜場(chǎng)景,XML 自定義 SQL 是不可或缺的利器。
- 主鍵生成、字段映射等基礎(chǔ)功能覆蓋面廣,足夠應(yīng)對(duì)大多數(shù)項(xiàng)目需求。
建議:
- 優(yōu)先使用 MP 提供的內(nèi)置方法,減少代碼冗余。
- 復(fù)雜業(yè)務(wù)邏輯時(shí),靈活使用自定義 SQL(尤其是 XML 文件)。
- 對(duì)于關(guān)聯(lián)查詢,合理使用
resultMap和嵌套映射。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- mybatis-plus如何使用sql的date_format()函數(shù)查詢數(shù)據(jù)
- MyBatis-Plus?實(shí)體類注解的實(shí)現(xiàn)示例
- Mybatis-Plus實(shí)體類繼承Model的使用小結(jié)
- MyBatis-Plus動(dòng)態(tài)返回實(shí)體類示例詳解
- Mybatis-plus如何提前獲取實(shí)體類用雪花算法生成的ID
- Mybatis-Plus實(shí)體類注解方法與mapper層和service層的CRUD方法
- mybatis-plus實(shí)體類中出現(xiàn)非數(shù)據(jù)庫映射字段解決辦法
- 詳解mybatis-plus實(shí)體類中字段和數(shù)據(jù)庫中字段名不對(duì)應(yīng)解決辦法
相關(guān)文章
Kotlin 語言中調(diào)用 JavaScript 方法實(shí)例詳解
這篇文章主要介紹了Kotlin 語言中調(diào)用 JavaScript 方法實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下2017-06-06
Spring依賴注入中的@Resource與@Autowired詳解
這篇文章主要介紹了Spring依賴注入中的@Resource與@Autowired詳解,提到Spring依賴注入,大家最先想到應(yīng)該是@Resource和@Autowired,對(duì)于Spring為什么要支持兩個(gè)這么類似的注解卻未提到,屬于知其然而不知其所以然,本文就來做詳細(xì)講解,需要的朋友可以參考下2023-09-09
java返回的List進(jìn)行add操作報(bào)錯(cuò)
本文主要介紹了java返回的List進(jìn)行add操作報(bào)錯(cuò),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-06-06
Java畢業(yè)設(shè)計(jì)實(shí)戰(zhàn)之校園一卡通系統(tǒng)的實(shí)現(xiàn)
這是一個(gè)使用了java+Springboot+Maven+mybatis+Vue+mysql+wd開發(fā)的校園一卡通系統(tǒng),是一個(gè)畢業(yè)設(shè)計(jì)的實(shí)戰(zhàn)練習(xí),具有校園一卡通系統(tǒng)該有的所有功能,感興趣的朋友快來看看吧2022-01-01
一種新的日期處理方式之JavaScript Temporal API
JavaScript Temporal API是一種為Web開發(fā)人員提供了一種新的處理日期和時(shí)間數(shù)據(jù)類型的方式。它的目的是使操作日期和時(shí)間更加簡(jiǎn)單和可靠,而且不用擔(dān)心歷史時(shí)區(qū)問題或全球化協(xié)調(diào)時(shí)間(UTC)之類的問題,感興趣的同學(xué)可以參考閱讀2023-05-05
Springboot MDC+logback實(shí)現(xiàn)日志追蹤的方法
MDC(Mapped Diagnostic Contexts)映射診斷上下文,該特征是logback提供的一種方便在多線程條件下的記錄日志的功能,這篇文章主要介紹了Springboot MDC+logback實(shí)現(xiàn)日志追蹤的方法,需要的朋友可以參考下2024-04-04
SpringMVC上傳文件的三種實(shí)現(xiàn)方式
本篇文章主要介紹了SpringMVC上傳文件的三種實(shí)現(xiàn)方式,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-12-12
SpringMvc/SpringBoot HTTP通信加解密的實(shí)現(xiàn)
這篇文章主要介紹了SpringMvc/SpringBoot HTTP通信加解密的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08

