MyBatis 是優秀的持久層框架,支援自定義 SQL、存儲過程、高級映射,消除絕大部分 JDBC 樣板代碼。本文從零構建 MyBatis 入門項目:Maven 依賴、核心配置文件、Mapper XML、動態代理接口、測試用例,覆蓋完整 CRUD 流程。
mybatis-demo
├── src/main/java
│ ├── com.example.mapper # Mapper 接口
│ ├── com.example.pojo # 實體類
│ └── com.example.test # 測試類
├── src/main/resources
│ ├── mybatis-config.xml # 核心配置
│ ├── db.properties # 數據庫配置
│ └── mapper # Mapper XML 目錄
│ └── UserMapper.xml
└── pom.xml
org.mybatis
mybatis
3.5.15
com.mysql
mysql-connector-j
8.0.33
com.zaxxer
HikariCP
5.0.1
ch.qos.logback
logback-classic
1.4.11
org.junit.jupiter
junit-jupiter
5.10.0
test
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis_demo?useSSL=false&serverTimezone=UTC
jdbc.username=root
jdbc.password=123456
@Data @NoArgsConstructor @AllArgsConstructor
public class User {
private Integer id;
private String username;
private String password;
private String email;
private LocalDateTime createTime;
}
public interface UserMapper {
// 註解式 SQL(簡單查詢)
@Select("SELECT * FROM user WHERE id = #{id}")
User selectById(Integer id);
@Select("SELECT * FROM user")
List selectAll();
@Insert("INSERT INTO user(username, password, email) VALUES(#{username}, #{password}, #{email})")
@Options(useGeneratedKeys = true, keyProperty = "id")
int insert(User user);
@Update("UPDATE user SET username=#{username}, email=#{email} WHERE id=#{id}")
int update(User user);
@Delete("DELETE FROM user WHERE id=#{id}")
int deleteById(Integer id);
// 複雜查詢使用 XML
List selectByCondition(@Param("username") String username,
@Param("email") String email);
}
id, username, password, email, create_time
class MyBatisTest {
private SqlSessionFactory sqlSessionFactory;
private UserMapper userMapper;
@BeforeEach
void init() throws IOException {
String resource = "mybatis-config.xml";
InputStream is = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
// 開啟會話,自動提交
SqlSession session = sqlSessionFactory.openSession(true);
userMapper = session.getMapper(UserMapper.class);
}
@Test
void testCRUD() {
// Insert
User user = new User(null, "zhangsan", "123456", "zhangsan@example.com", null);
int rows = userMapper.insert(user);
assertEquals(1, rows);
System.out.println("生成 ID: " + user.getId()); // 回填自增 ID
// Select
User found = userMapper.selectById(user.getId());
assertNotNull(found);
assertEquals("zhangsan", found.getUsername());
// Update
found.setEmail("new@example.com");
assertEquals(1, userMapper.update(found));
// List
List list = userMapper.selectAll();
assertFalse(list.isEmpty());
// Condition
List cond = userMapper.selectByCondition("zhang", null);
assertEquals(1, cond.size());
// Delete
assertEquals(1, userMapper.deleteById(user.getId()));
assertNull(userMapper.selectById(user.getId()));
}
}
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
// 內部:XMLConfigBuilder 解析配置 → Configuration 對象 → DefaultSqlSessionFactory
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
// 內部:MapperProxyFactory.newInstance() → MapperProxy.invoke()
// 1. 解析方法簽名 → MappedStatement
// 2. 綁定參數 → BoundSql
// 3. 執行器 Executor 執行 SQL
// 4. 結果映射 ResultSetHandler
| 組件 | 職責 |
|---|---|
| Configuration | 全局配置中心,持有 MappedStatement、TypeHandler、Cache 等 |
| SqlSession | 會話入口,提供 CRUD 方法、事務控制、獲取 Mapper 代理 |
| Executor | 執行器接口:Simple/Reuse/BatchExecutor,負責 SQL 執行、緩存 |
| StatementHandler | 預處理語句處理:參數綁定、SQL 執行 |
| ResultSetHandler | 結果集映射:ResultMap、類型轉換、嵌套結果 |
| ParameterHandler | 參數處理:#{}/${} 替換、TypeHandler 轉換 |
<if>、<choose>、<trim>、<foreach> 構建靈活查詢<resultMap> + <association>/<collection> 處理一對一/一對多MapperScannerConfigurer 自動掃描、事務管理、@TransactionalMyBatis 以「SQL 為中心」設計,保留 SQL 完全控制權,適合複雜查詢、性能調優場景。入門關鍵:配置文件結構、Mapper 接口映射、動態代理原理、結果映射。建議:簡單查詢用註解,複雜查詢用 XML;善用 resultMap 解決字段映射;生產環境必配連接池、日誌、緩存策略。掌握本文完整流程,即可獨立開發 MyBatis 持久層模塊。