MyBatis 注解Annotation實現(xiàn)CRUD操作全解析
MyBatis 提供了 注解(Annotation) 方式來實現(xiàn) CRUD 操作,適用于簡單、輕量級的數(shù)據(jù)庫交互場景。相比 XML 配置,注解方式將 SQL 直接寫在 Mapper 接口方法上,代碼更緊湊,開發(fā)效率更高。
一、MyBatis 注解 CRUD 核心注解
| 注解 | 作用 | 說明 |
|---|---|---|
@Select | 查詢 | 對應(yīng) SELECT 語句 |
@Insert | 插入 | 對應(yīng) INSERT 語句 |
@Update | 更新 | 對應(yīng) UPDATE 語句 |
@Delete | 刪除 | 對應(yīng) DELETE 語句 |
@Param | 參數(shù)綁定 | 多參數(shù)時指定參數(shù)名 |
@Options | 配置選項 | 如主鍵回填、緩存等 |
@Results / @Result | 結(jié)果映射 | 替代 <resultMap> |
@SelectProvider 等 | 動態(tài) SQL(高級) | 通過類方法生成 SQL(較少用) |
?? 注意:MyBatis 注解 不支持
<if>、<foreach>等動態(tài)標(biāo)簽,復(fù)雜邏輯仍需 XML。
二、準(zhǔn)備工作
1. 實體類(User.java)
public class User {
private Long id;
private String name;
private String email;
// 構(gòu)造函數(shù)、getter/setter 略
}2. 數(shù)據(jù)庫表(MySQL 示例)
CREATE TABLE users (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50) NOT NULL,
email VARCHAR(100)
);三、注解實現(xiàn) CRUD 完整示例
Mapper 接口:UserMapper.java
import org.apache.ibatis.annotations.*;
import java.util.List;
public interface UserMapper {
// 1. 新增(INSERT)
@Insert("INSERT INTO users(name, email) VALUES(#{name}, #{email})")
@Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")
int insert(User user);
// 2. 根據(jù) ID 查詢(SELECT)
@Select("SELECT * FROM users WHERE id = #{id}")
User selectById(@Param("id") Long id);
// 3. 查詢所有
@Select("SELECT * FROM users")
List<User> selectAll();
// 4. 更新(UPDATE)
@Update("UPDATE users SET name = #{name}, email = #{email} WHERE id = #{id}")
int update(User user);
// 5. 刪除(DELETE)
@Delete("DELETE FROM users WHERE id = #{id}")
int deleteById(@Param("id") Long id);
// 6. 帶條件查詢(多參數(shù))
@Select("SELECT * FROM users WHERE name LIKE CONCAT('%', #{name}, '%') AND email = #{email}")
List<User> findByNameAndEmail(@Param("name") String name, @Param("email") String email);
}四、關(guān)鍵細(xì)節(jié)詳解
1. 主鍵自增回填(@Options)
@Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")
useGeneratedKeys = true:啟用 JDBC 獲取自增主鍵;keyProperty = "id":將生成的主鍵值賦給 User 對象的id字段;keyColumn = "id":數(shù)據(jù)庫主鍵列名(通??墒÷?,MyBatis 自動推斷)。
? 插入后,
user.getId()即可獲得數(shù)據(jù)庫生成的 ID。
2. 多參數(shù)傳遞(@Param)
當(dāng)方法有多個參數(shù)時,必須使用 @Param 指定名稱:
@Select("SELECT * FROM users WHERE name = #{name} AND email = #{email}")
User findByTwoParams(@Param("name") String name, @Param("email") String email);否則 MyBatis 無法識別 #{name} 對應(yīng)哪個參數(shù)。
3. 字段映射(@Results)
如果數(shù)據(jù)庫字段與 Java 屬性名不一致(如 user_name vs userName),可用 @Results 顯式映射:
@Select("SELECT user_id, user_name, user_email FROM users WHERE user_id = #{id}")
@Results({
@Result(property = "id", column = "user_id"),
@Result(property = "name", column = "user_name"),
@Result(property = "email", column = "user_email")
})
User selectByIdWithMapping(@Param("id") Long id);?? 若開啟 mapUnderscoreToCamelCase,則無需手動映射。
五、測試示例(JUnit + MyBatis)
@Test
public void testCrud() throws IOException {
try (SqlSession session = sqlSessionFactory.openSession()) {
UserMapper mapper = session.getMapper(UserMapper.class);
// 插入
User user = new User();
user.setName("王五");
user.setEmail("wangwu@example.com");
mapper.insert(user); // 此時 user.id 已被填充
System.out.println("插入ID: " + user.getId());
// 查詢
User found = mapper.selectById(user.getId());
System.out.println("查詢結(jié)果: " + found.getName());
// 更新
found.setEmail("new_wangwu@example.com");
mapper.update(found);
// 刪除
mapper.deleteById(found.getId());
session.commit(); // 注意:DML 操作需提交事務(wù)
}
}?? 重要:MyBatis 默認(rèn)不自動提交事務(wù)!執(zhí)行 INSERT/UPDATE/DELETE 后需調(diào)用
session.commit(),或配置autoCommit=true(不推薦生產(chǎn)環(huán)境使用)。
六、優(yōu)點與局限性
? 優(yōu)點
- 代碼簡潔:SQL 與接口方法緊耦合,無需額外 XML 文件;
- 開發(fā)快速:適合單表、靜態(tài) SQL 場景;
- 易于理解:CRUD 邏輯一目了然。
? 局限性
| 問題 | 說明 |
|---|---|
| 不支持動態(tài) SQL | 無法使用 <if>、<choose>、<foreach> 等標(biāo)簽 |
| SQL 復(fù)雜度受限 | 多表 JOIN、嵌套查詢難以維護(hù) |
| 無法復(fù)用 SQL 片段 | 不能像 XML 那樣用 <sql> 提取公共部分 |
| 可讀性差(長 SQL) | SQL 寫在字符串中,無語法高亮,易出錯 |
| 調(diào)試?yán)щy | SQL 錯誤只能運行時發(fā)現(xiàn),IDE 無法校驗 |
七、盡管注解方便,但在以下場景中,XML 映射文件是不可替代的:
1.動態(tài) SQL 支持強(qiáng)大
MyBatis 的核心優(yōu)勢之一是 動態(tài) SQL(如 <if>、<choose>、<foreach> 等),而注解中寫動態(tài) SQL 極其困難甚至不可讀。
? 注解寫動態(tài) SQL(不推薦):
@Select("<script>" +
"SELECT * FROM users WHERE 1=1 " +
"<if test='name != null'> AND name LIKE CONCAT('%', #{name}, '%') </if>" +
"<if test='email != null'> AND email = #{email} </if>" +
"</script>")
List<User> findUsers(@Param("name") String name, @Param("email") String email);- 字符串拼接易出錯;
- 無法格式化,難以維護(hù);
- 不支持 IDE 語法高亮和校驗。
? XML 寫法(清晰優(yōu)雅):
<select id="findUsers" resultType="User">
SELECT * FROM users
<where>
<if test="name != null">
AND name LIKE CONCAT('%', #{name}, '%')
</if>
<if test="email != null">
AND email = #{email}
</if>
</where>
</select>?? 結(jié)論:只要涉及條件組合、分頁、批量操作等,XML 是唯一合理選擇。
2.復(fù)雜結(jié)果映射(ResultMap)
當(dāng)實體類與數(shù)據(jù)庫字段命名不一致,或存在一對一/一對多關(guān)聯(lián)查詢時,需使用 <resultMap>。
示例:用戶 + 角色關(guān)聯(lián)
<resultMap id="UserWithRoles" type="User">
<id property="id" column="user_id"/>
<result property="name" column="user_name"/>
<collection property="roles" ofType="Role">
<id property="id" column="role_id"/>
<result property="name" column="role_name"/>
</collection>
</resultMap>
<select id="selectUserWithRoles" resultMap="UserWithRoles">
SELECT u.id AS user_id, u.name AS user_name,
r.id AS role_id, r.name AS role_name
FROM users u
LEFT JOIN user_roles ur ON u.id = ur.user_id
LEFT JOIN roles r ON ur.role_id = r.id
WHERE u.id = #{id}
</select>? 注解無法優(yōu)雅表達(dá)這種嵌套映射,只能通過
@Results手動配置,代碼冗長且不支持集合映射。
3.SQL 復(fù)用與模塊化
XML 支持 <sql> 片段復(fù)用:
<sql id="userColumns">id, name, email</sql>
<select id="selectAll" resultType="User">
SELECT <include refid="userColumns"/> FROM users
</select>注解無法實現(xiàn) SQL 片段提取,導(dǎo)致重復(fù)代碼。
4.可維護(hù)性與團(tuán)隊協(xié)作
- XML 文件可被 DBA 審查、優(yōu)化;
- SQL 與 Java 代碼分離,符合“關(guān)注點分離”原則;
- 更容易做 SQL 性能調(diào)優(yōu)、日志追蹤;
- 支持 MyBatis Generator 自動生成 XML 和實體類。
5.特殊 SQL 語法兼容性更好
某些數(shù)據(jù)庫特有語法(如 Oracle 的 MERGE、PostgreSQL 的 JSON 操作)在 XML 中更易書寫和調(diào)試。
八、總結(jié)
| 功能 | 注解實現(xiàn) | 是否推薦 |
|---|---|---|
| 單表 INSERT/UPDATE/DELETE | ? 支持 | ? 簡單場景推薦 |
| 單條件 SELECT | ? 支持 | ? |
| 多條件動態(tài)查詢 | ? 不支持(需拼字符串) | ? 不推薦 |
| 關(guān)聯(lián)查詢(JOIN) | ?? 可寫但難維護(hù) | ? 不推薦 |
| 主鍵回填 | ? 支持(@Options) | ? |
| 字段映射 | ? 支持(@Results) | ?? 開啟駝峰更佳 |
?? 結(jié)論:
MyBatis 注解是 輕量級 CRUD 的利器,但 不是萬能方案。
在快速開發(fā)、腳本工具、微服務(wù) DAO 層等場景下非常高效;
但在企業(yè)級應(yīng)用中,XML 仍是主力,注解僅作補(bǔ)充。注解是“糖”,XML 是“飯”。
糖可以提味,但不能當(dāng)飯吃。在真實業(yè)務(wù)系統(tǒng)中,XML 的靈活性、可讀性和功能完整性使其具有不可替代的地位。
到此這篇關(guān)于MyBatis 注解Annotation實現(xiàn)CRUD操作全解析的文章就介紹到這了,更多相關(guān)MyBatis 注解實現(xiàn)CRUD內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot 使用 Ehcache 作為緩存的操作方法
這篇文章主要介紹了SpringBoot 如何使用 Ehcache 作為緩存,我們通過添加 Ehcache 依賴、創(chuàng)建 Ehcache 配置文件并在 Spring Boot 應(yīng)用程序的配置文件中啟用 Ehcache 緩存,來配置 Ehcache 緩存,需要的朋友可以參考下2023-06-06
Mybatis分頁插件PageHelper的配置和簡單使用方法(推薦)
在使用Java Spring開發(fā)的時候,Mybatis算是對數(shù)據(jù)庫操作的利器了。這篇文章主要介紹了Mybatis分頁插件PageHelper的配置和使用方法,需要的朋友可以參考下2017-12-12
使用log4j2打印mybatis的sql執(zhí)行日志方式
這篇文章主要介紹了使用log4j2打印mybatis的sql執(zhí)行日志方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-09-09
Java實現(xiàn)將Doc/Docx格式的Word文檔轉(zhuǎn)換為PDF文件
這篇文章主要為大家詳細(xì)介紹了如何通過Java將Word文檔轉(zhuǎn)換為PDF、PDF/A和密碼保護(hù)的PDF文件,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解下2025-08-08
AQS(AbstractQueuedSynchronizer)抽象隊列同步器及工作原理解析
AQS是用來構(gòu)建鎖或者其他同步器組件的重量級基礎(chǔ)框架及整個JUC體系的基石,通過內(nèi)置的FIFO對列來完成資源獲取線程的排隊工作,并通過一個int類型變量表示持有鎖的狀態(tài),本文給大家詳細(xì)介紹下AQS抽象隊列同步器的相關(guān)知識,感興趣的朋友一起看看吧2022-03-03
mybatis實現(xiàn)表與對象的關(guān)聯(lián)關(guān)系_動力節(jié)點Java學(xué)院整理
這篇文章主要介紹了mybatis實現(xiàn)表與對象的關(guān)聯(lián)關(guān)系_動力節(jié)點Java學(xué)院整理,需要的朋友可以參考下2017-09-09
Java之使用POI教你玩轉(zhuǎn)Excel導(dǎo)入與導(dǎo)出
這篇文章主要介紹了Java之使用POI教你玩轉(zhuǎn)Excel導(dǎo)入與導(dǎo)出,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-10-10

