MyBatis 是半自動 ORM 持久層框架:支持原生 SQL、存儲過程、高級映射,消除 95%+ JDBC 樣板代碼(連接獲取、參數綁定、結果集映射、資源關閉)。通過 XML 或註解將接口方法映射為 SQL,POJO 自動映射查詢結果。
<dependencies>
<!-- MyBatis 核心 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.13</version>
</dependency>
<!-- MySQL 驅動 -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.0.33</version>
</dependency>
<!-- JUnit 5 測試 -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.10.0</version>
<scope>test</scope>
</dependency>
</dependencies>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis_demo?useSSL=false&serverTimezone=UTC"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="mapper/UserMapper.xml"/>
</mappers>
</configuration>
關鍵點:JDBC URL 必須使用 localhost(非 127.0.0.1)以避免某些環境下的連接超時;POOLED 數據源內置連接池,生產建議替換為 HikariCP。
<mapper namespace="com.demo.mapper.UserMapper">
<resultMap id="userMap" type="com.demo.entity.User">
<id property="id" column="id"/>
<result property="username" column="username"/>
<result property="email" column="email"/>
<result property="createTime" column="create_time"/>
</resultMap>
<select id="selectById" resultMap="userMap">
SELECT * FROM t_user WHERE id = #{id}
</select>
<select id="selectAll" resultMap="userMap">
SELECT * FROM t_user
</select>
<insert id="insert" parameterType="com.demo.entity.User" useGeneratedKeys="true" keyProperty="id">
INSERT INTO t_user(username, email) VALUES(#{username}, #{email})
</insert>
<update id="update" parameterType="com.demo.entity.User">
UPDATE t_user SET username=#{username}, email=#{email} WHERE id=#{id}
</update>
<delete id="deleteById" parameterType="Long">
DELETE FROM t_user WHERE id = #{id}
</delete>
</mapper>
// User.java
@Data @NoArgsConstructor @AllArgsConstructor
public class User {
private Long id;
private String username;
private String email;
private LocalDateTime createTime;
}
// UserMapper.java
public interface UserMapper {
User selectById(Long id);
List<User> selectAll();
int insert(User user);
int update(User user);
int deleteById(Long id);
}
SqlSessionFactory:線程安全,應用啟動時構建一次,單例保存SqlSession:**非線程安全**,每請求/事務一個,用完必須 close() 歸還連接SqlSessionTemplate 代理管理,自動綁定事務
// 獨立模式標準用法
try (SqlSession session = factory.openSession()) {
UserMapper mapper = session.getMapper(UserMapper.class);
User user = mapper.selectById(1L);
session.commit(); // 寫操作需提交
return user;
}
@BeforeEach void init() throws IOException {
String resource = "mybatis-config.xml";
InputStream is = Resources.getResourceAsStream(resource);
factory = new SqlSessionFactoryBuilder().build(is);
}
@Test void testCRUD() {
try (SqlSession session = factory.openSession(true)) { // autoCommit=true
UserMapper mapper = session.getMapper(UserMapper.class);
// Insert
User u = new User(null, "test", "test@demo.com", null);
assertEquals(1, mapper.insert(u));
assertNotNull(u.getId()); // 回寫自增主鍵
// Select
User found = mapper.selectById(u.getId());
assertEquals("test", found.getUsername());
// Update
found.setEmail("updated@demo.com");
assertEquals(1, mapper.update(found));
// Delete
assertEquals(1, mapper.deleteById(u.getId()));
assertNull(mapper.selectById(u.getId()));
}
}
create_time → createTime)、關聯查詢(association/collection)、構造方法注入(constructor)<where>、<if>、<choose/when/otherwise>、<foreach> 批量插入/IN 查詢mapperLocations 掃描自動綁定@Param 或封裝 POJO/Map#{} 預編譯防注入,${} 直接拼接(僅用於表名、排序列等不可預編譯場景)LIMIT/OFFSET@Transactional),DAO 單純執行 SQL