首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

MyBatis 獲取 SqlSession 完整指南:XML 與註解雙模式實戰

     編輯:Java 相關知識

核心流程圖解

Resources.getResourceAsReader("mybatis-config.xml")
        ↓
SqlSessionFactoryBuilder().build(reader) → SqlSessionFactory
        ↓
sqlSessionFactory.openSession() → SqlSession
        ↓
session.getMapper(Mapper接口) → Mapper代理對象
        ↓
mapper.xxx() → 執行 SQL → 返回結果
        ↓
session.close() / session.commit()

方式一:XML 配置模式 (傳統、通用)

1. 核心配置文件 mybatis-config.xml

<?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>
    <properties resource="jdbc.properties"/>
    
    <typeAliases>
        <package name="com.example.entity"/>
    </typeAliases>
    
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>
    
    <mappers>
        <package name="com.example.mapper"/>
    </mappers>
</configuration>

2. 映射器接口 UserMapper.java

public interface UserMapper {
    User selectById(@Param("id") Long id);
    List selectAll();
    int insert(User user);
    int update(User user);
    int deleteById(Long id);
}

3. 映射器 XML UserMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
  "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mapper.UserMapper">
    <resultMap id="userMap" type="User">
        <id property="id" column="id"/>
        <result property="username" column="username"/>
        <result property="email" column="email"/>
    </resultMap>
    
    <select id="selectById" resultMap="userMap">
        SELECT id, username, email FROM t_user WHERE id = #{id}
    </select>
    
    <select id="selectAll" resultMap="userMap">
        SELECT id, username, email FROM t_user
    </select>
    
    <insert id="insert" parameterType="User" useGeneratedKeys="true" keyProperty="id">
        INSERT INTO t_user(username, email) VALUES(#{username}, #{email})
    </insert>
    
    <update id="update" parameterType="User">
        UPDATE t_user SET username=#{username}, email=#{email} WHERE id=#{id}
    </update>
    
    <delete id="deleteById">
        DELETE FROM t_user WHERE id = #{id}
    </delete>
</mapper>

4. 測試代碼

public class MyBatisXmlTest {
    private SqlSessionFactory sqlSessionFactory;
    
    @Before
    public void init() throws IOException {
        try (Reader reader = Resources.getResourceAsReader("mybatis-config.xml")) {
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
        }
    }
    
    @Test
    public void testCrud() {
        try (SqlSession session = sqlSessionFactory.openSession(true)) { // autoCommit=true
            UserMapper mapper = session.getMapper(UserMapper.class);
            
            // 插入
            User user = new User(null, "alice", "alice@example.com");
            mapper.insert(user);
            System.out.println("生成 ID: " + user.getId());
            
            // 查詢
            User found = mapper.selectById(user.getId());
            assertEquals("alice", found.getUsername());
            
            // 更新
            found.setEmail("alice_new@example.com");
            mapper.update(found);
            
            // 刪除
            mapper.deleteById(user.getId());
        }
    }
}

方式二:純註解模式 (無 XML,適合簡單 CRUD)

public interface UserMapper {
    @Select("SELECT id, username, email FROM t_user WHERE id = #{id}")
    @Results(id = "userMap", value = {
        @Result(property = "id", column = "id", id = true),
        @Result(property = "username", column = "username"),
        @Result(property = "email", column = "email")
    })
    User selectById(Long id);
    
    @Select("SELECT id, username, email FROM t_user")
    @ResultMap("userMap")
    List selectAll();
    
    @Insert("INSERT INTO t_user(username, email) VALUES(#{username}, #{email})")
    @Options(useGeneratedKeys = true, keyProperty = "id")
    int insert(User user);
    
    @Update("UPDATE t_user SET username=#{username}, email=#{email} WHERE id=#{id}")
    int update(User user);
    
    @Delete("DELETE FROM t_user WHERE id = #{id}")
    int deleteById(Long id);
}

註解模式啟動:Configuration 掃描包 <package name="com.example.mapper"/> 即可自動解析註解,無需 XML 文件。

SqlSession 關鍵特性與最佳實踐

1. 線程不安全 —— 請勿共享

// ❌ 錯誤:單例共享
@Component
public class BadDao {
    @Autowired SqlSession session; // 併發下數據錯亂
}

// ✅ 正確:每次業務獲取新會話
@Repository
public class GoodDao {
    @Autowired SqlSessionFactory factory;
    
    public User getUser(Long id) {
        try (SqlSession session = factory.openSession()) {
            return session.getMapper(UserMapper.class).selectById(id);
        }
    }
}

2. 事務控制

模式獲取方式提交/回滾適用場景
手動事務openSession(false)session.commit() / session.rollback()批量導入、複雜業務邏輯
自動提交openSession(true)每條語句自動提交簡單查詢、測試代碼
Spring 管理@Transactional + Mapper 注入框架自動控制企業級應用 (推薦)

3. 執行器類型選擇

// SIMPLE: 預設,每條語句創建 PreparedStatement
factory.openSession(ExecutorType.SIMPLE);

// REUSE: 重用 PreparedStatement
factory.openSession(ExecutorType.REUSE);

// BATCH: 批量更新,需手動 commit/flush
factory.openSession(ExecutorType.BATCH);

Spring 整合下的 SqlSession 獲取 (實戰標準)

// 1. Mapper 掃描 (無需手動獲取 SqlSession)
@MapperScan("com.example.mapper")
@Configuration
public class MyBatisConfig {}

// 2. Service 直接注入 Mapper
@Service
@RequiredArgsConstructor
public class UserService {
    private final UserMapper userMapper; // Spring 自動注入代理
    
    @Transactional
    public void register(User user) {
        userMapper.insert(user); // 同一事務內
        // 其他業務...
    }
}

常見問題排查

現象原因解決
BindingException: Invalid bound statementNamespace/ID 拼寫錯誤、XML 未掃描核對 namespace = 接口全限定名、id = 方法名、mapperLocations 路徑
插入後 ID 為 null缺 useGeneratedKeys="true" keyProperty="id"XML/註解添加自增主鍵回填配置
關聯查詢字段為 null列名與屬性名不匹配用 <resultMap> 或 SQL 別名 AS 映射
併發下數據錯亂SqlSession 被多線程共享每請求一個 Session,或用 Spring 代理 Mapper
事務不生效未開啟 @EnableTransactionManagement 或調用非公共方法檢查事務配置、方法可見性、異常回滾規則

總結

獲取 SqlSession 核心三步:Resources → SqlSessionFactoryBuilder → SqlSessionFactory → openSession()。XML 模式適合複雜 SQL、動態條件、存儲過程;註解模式適合簡單 CRUD、微服務輕量化。生產環境強烈建議整合 Spring,由容器管理 SqlSession 生命週期與事務,直接注入 Mapper 接口使用,避免手動管理帶來的線程安全與事務邊界問題。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved