最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

MyBatis會(huì)話(huà)模塊詳解

 更新時(shí)間:2026年02月09日 10:21:41   作者:雨中飄蕩的記憶  
本文主要介紹了MyBatis會(huì)話(huà)模塊詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

一、MyBatis整體架構(gòu)與會(huì)話(huà)模塊

MyBatis是一個(gè)優(yōu)秀的持久層框架,它支持定制化SQL、存儲(chǔ)過(guò)程以及高級(jí)映射。MyBatis避免了幾乎所有的JDBC代碼和手動(dòng)設(shè)置參數(shù)以及獲取結(jié)果集的工作。

1.1 MyBatis整體架構(gòu)

MyBatis采用分層架構(gòu)設(shè)計(jì),從上到下分為:

  • 應(yīng)用層 — 與用戶(hù)應(yīng)用程序直接交互
  • 接口層 — 提供SqlSession和Mapper接口
  • 核心處理層 — 包括SQL解析、執(zhí)行、結(jié)果映射
  • 基礎(chǔ)支撐層 — 包括反射、類(lèi)型處理、日志、緩存、事務(wù)
  • 數(shù)據(jù)層 — 數(shù)據(jù)源管理、連接池、JDBC驅(qū)動(dòng)

會(huì)話(huà)模塊位于接口層,是MyBatis與應(yīng)用程序交互的主要入口。

1.2 會(huì)話(huà)模塊的核心職責(zé)

會(huì)話(huà)模塊在MyBatis中承擔(dān)以下核心職責(zé):

? 數(shù)據(jù)庫(kù)操作接口 — 提供insert、update、delete、select等方法
? SqlSession生命周期管理 — 創(chuàng)建、使用、關(guān)閉SqlSession
? 事務(wù)控制 — 管理事務(wù)的開(kāi)啟、提交、回滾
? Mapper管理 — 獲取Mapper接口的代理對(duì)象
? 批量操作支持 — 提供批量執(zhí)行SQL的能力

二、SqlSession接口詳解

SqlSession是MyBatis的核心接口之一,它定義了所有數(shù)據(jù)庫(kù)操作的方法。

2.1 SqlSession核心方法分類(lèi)

// 查詢(xún)單個(gè)對(duì)象
<T> T selectOne(String statement);
<T> T selectOne(String statement, Object parameter);

// 查詢(xún)列表
<E> List<E> selectList(String statement);
<E> List<E> selectList(String statement, Object parameter);

// 查詢(xún)Map
<K, V> Map<K, V> selectMap(String statement, String mapKey);

// 游標(biāo)查詢(xún)
<T> Cursor<T> selectCursor(String statement);
// 插入
int insert(String statement);
int insert(String statement, Object parameter);

// 更新
int update(String statement);
int update(String statement, Object parameter);

// 刪除
int delete(String statement);
int delete(String statement, Object parameter);
// 提交事務(wù)
void commit();
void commit(boolean force);

// 回滾事務(wù)
void rollback();
void rollback(boolean force);
// 獲取Mapper代理對(duì)象
<T> T getMapper(Class<T> type);
// 1. 獲取SqlSessionFactory
SqlSessionFactory factory = new SqlSessionFactoryBuilder()
    .build(Resources.getResourceAsStream("mybatis-config.xml"));

// 2. 打開(kāi)SqlSession
try (SqlSession session = factory.openSession()) {
    // 3. 執(zhí)行SQL
    User user = session.selectOne(
        "com.example.mapper.UserMapper.selectById", 1);
    System.out.println(user);
}
try (SqlSession session = factory.openSession()) {
    // 獲取Mapper代理對(duì)象
    UserMapper mapper = session.getMapper(UserMapper.class);

    // 調(diào)用Mapper方法
    User user = mapper.selectById(1);
    System.out.println(user);

    session.commit();
}

三、SqlSession的實(shí)現(xiàn)類(lèi)

MyBatis提供了兩個(gè)主要的SqlSession實(shí)現(xiàn)類(lèi)。

3.1 DefaultSqlSession

DefaultSqlSession是SqlSession的默認(rèn)實(shí)現(xiàn)類(lèi),最常用的實(shí)現(xiàn)。

核心代碼片段:

public class DefaultSqlSession implements SqlSession {

    private final Configuration configuration;
    private final Executor executor;

    @Override
    public <T> T selectOne(String statement, Object parameter) {
        List<T> list = this.selectList(statement, parameter);
        if (list.size() == 1) {
            return list.get(0);
        } else if (list.size() > 1) {
            throw new TooManyResultsException(
                "Expected one result but found: " + list.size());
        }
        return null;
    }

    @Override
    public void commit(boolean force) {
        try {
            executor.commit(isCommitOrRollbackRequired(force));
            dirty = false;
        } catch (Exception e) {
            throw ExceptionFactory.wrapException(
                "Error committing transaction.", e);
        }
    }
}

3.2 SqlSessionManager

SqlSessionManager同時(shí)實(shí)現(xiàn)了SqlSession和SqlSessionFactory接口,既可以作為SqlSession使用,也可以作為工廠(chǎng)使用。

public class SqlSessionManager 
    implements SqlSessionFactory, SqlSession {

    private final SqlSessionFactory sqlSessionFactory;
    private final SqlSession sqlSessionProxy;
    private ThreadLocal<SqlSession> localSqlSession 
        = new ThreadLocal<>();

    // 開(kāi)啟本地Session
    public void startManagedSession() {
        this.localSqlSession.set(openSession());
    }

    // 關(guān)閉本地Session
    public void closeManagedSession() {
        SqlSession sqlSession = localSqlSession.get();
        if (sqlSession != null) {
            try {
                sqlSession.close();
            } finally {
                localSqlSession.remove();
            }
        }
    }
}

四、SqlSessionFactory工廠(chǎng)

SqlSessionFactory是創(chuàng)建SqlSession的工廠(chǎng)接口。

4.1 SqlSessionFactory接口方法

public interface SqlSessionFactory {

    // 常用方法:打開(kāi)Session
    SqlSession openSession();

    // 指定ExecutorType
    SqlSession openSession(ExecutorType execType);

    // 指定是否自動(dòng)提交
    SqlSession openSession(boolean autoCommit);

    // 指定事務(wù)隔離級(jí)別
    SqlSession openSession(TransactionIsolationLevel level);

    // 使用指定連接
    SqlSession openSession(Connection connection);
}

4.2 DefaultSqlSessionFactory核心流程

創(chuàng)建SqlSession的完整流程:

private SqlSession openSessionFromDataSource(
    ExecutorType execType,
    TransactionIsolationLevel level,
    boolean autoCommit) {

    Transaction tx = null;
    try {
        //獲取環(huán)境配置
        Environment environment = configuration.getEnvironment();

        //創(chuàng)建事務(wù)工廠(chǎng)
        TransactionFactory transactionFactory = 
            getTransactionFactoryFromEnvironment(environment);

        //創(chuàng)建事務(wù)
        tx = transactionFactory.newTransaction(
            environment.getDataSource(), level, autoCommit);

        //創(chuàng)建執(zhí)行器
        Executor executor = configuration.newExecutor(tx, execType);

        //創(chuàng)建DefaultSqlSession
        return new DefaultSqlSession(configuration, executor, autoCommit);
    } catch (Exception e) {
        closeTransaction(tx);
        throw ExceptionFactory.wrapException(
            "Error opening session.", e);
    }
}

五、SqlSession生命周期管理

SqlSession的生命周期管理非常重要,不當(dāng)使用會(huì)導(dǎo)致資源泄漏。

5.1 SqlSession的三個(gè)階段

// 方式1:默認(rèn)創(chuàng)建
SqlSession session = sqlSessionFactory.openSession();

// 方式2:自動(dòng)提交
SqlSession session = sqlSessionFactory.openSession(true);

// 方式3:指定Executor類(lèi)型
SqlSession session = sqlSessionFactory.openSession(
    ExecutorType.BATCH);

// 方式4:事務(wù)隔離級(jí)別
SqlSession session = sqlSessionFactory.openSession(
    TransactionIsolationLevel.READ_COMMITTED);
try (SqlSession session = factory.openSession()) {
    // 執(zhí)行查詢(xún)
    User user = session.selectOne(
        "com.example.mapper.UserMapper.selectById", 1);

    // 執(zhí)行更新
    User updateUser = new User();
    updateUser.setId(1);
    updateUser.setName("張三");
    session.update(
        "com.example.mapper.UserMapper.update", updateUser);

    // 提交事務(wù)
    session.commit();
}
// 推薦方式:try-with-resources
try (SqlSession session = factory.openSession()) {
    // 使用session
} // 自動(dòng)關(guān)閉

// 傳統(tǒng)方式
SqlSession session = null;
try {
    session = factory.openSession();
    // 使用session
} finally {
    if (session != null) {
        session.close();
    }
}

重要原則:SqlSession的作用域應(yīng)該是方法級(jí)別的!

// 錯(cuò)誤:SqlSession作為成員變量
public class UserService {
    private SqlSession session; // ? 不要這樣做!

    public User getUserById(int id) {
        return session.selectOne(
            "com.example.mapper.UserMapper.selectById", id);
    }
}
// 正確:SqlSession在方法中創(chuàng)建和關(guān)閉
public class UserService {
    private SqlSessionFactory factory;

    public User getUserById(int id) {
        try (SqlSession session = factory.openSession()) {
            return session.selectOne(
                "com.example.mapper.UserMapper.selectById", id);
        }
    }
}

5.2 線(xiàn)程安全問(wèn)題

SqlSession不是線(xiàn)程安全的,每個(gè)線(xiàn)程都應(yīng)該有自己的SqlSession實(shí)例!

public class UserService {
    // ? 多個(gè)線(xiàn)程共享同一個(gè)SqlSession
    private SqlSession session = factory.openSession();
}
public class UserService {
    private SqlSessionFactory factory;

    public User getUserById(int id) {
        // ? 每次調(diào)用都創(chuàng)建新的SqlSession
        try (SqlSession session = factory.openSession()) {
            return session.selectOne("...", id);
        }
    }
}

5.3 ThreadLocal管理模式

在某些場(chǎng)景下,可以使用ThreadLocal管理SqlSession:

public class SqlSessionManager {

    private static final ThreadLocal<SqlSession> LOCAL_SESSION 
        = new ThreadLocal<>();
    private static SqlSessionFactory factory;

    // 獲取當(dāng)前線(xiàn)程的SqlSession
    public static SqlSession getSession() {
        SqlSession session = LOCAL_SESSION.get();
        if (session == null) {
            session = factory.openSession();
            LOCAL_SESSION.set(session);
        }
        return session;
    }

    // 關(guān)閉當(dāng)前線(xiàn)程的SqlSession
    public static void closeSession() {
        SqlSession session = LOCAL_SESSION.get();
        if (session != null) {
            session.close();
            LOCAL_SESSION.remove();
        }
    }
}

六、事務(wù)控制機(jī)制

SqlSession提供了完善的事務(wù)控制機(jī)制。

6.1 自動(dòng)提交 vs 手動(dòng)提交

// 不自動(dòng)提交(默認(rèn))
SqlSession session = factory.openSession();
session.insert("...");
session.commit(); // 需要手動(dòng)提交

//自動(dòng)提交
SqlSession session = factory.openSession(true);
session.insert("..."); // 自動(dòng)提交

6.2 手動(dòng)事務(wù)控制實(shí)戰(zhàn)

try (SqlSession session = factory.openSession()) {
    try {
        // 1.插入用戶(hù)
        User user = new User();
        user.setName("張三");
        user.setEmail("zhangsan@example.com");
        session.insert(
            "com.example.mapper.UserMapper.insert", user);

        //2.插入訂單
        Order order = new Order();
        order.setUserId(user.getId());
        order.setAmount(100.0);
        session.insert(
            "com.example.mapper.OrderMapper.insert", order);

        //3.提交事務(wù)
        session.commit();
    } catch (Exception e) {
        //4.回滾事務(wù)
        session.rollback();
        throw e;
    }
}

6.3 事務(wù)隔離級(jí)別

MyBatis支持設(shè)置事務(wù)隔離級(jí)別:

SqlSession session = factory.openSession(
    TransactionIsolationLevel.READ_COMMITTED);

支持的隔離級(jí)別:

隔離級(jí)別說(shuō)明適用場(chǎng)景
NONE無(wú)事務(wù)隔離不推薦
READ_UNCOMMITTED讀未提交極少使用
READ_COMMITTED讀已提交大多數(shù)數(shù)據(jù)庫(kù)默認(rèn)
REPEATABLE_READ可重復(fù)讀MySQL默認(rèn)
SERIALIZABLE串行化最高隔離級(jí)別

6.4 批量操作的事務(wù)控制

try (SqlSession session = factory.openSession(
    ExecutorType.BATCH, false)) {
    try {
        UserMapper mapper = session.getMapper(UserMapper.class);

        // 批量插入
        for (int i = 0; i < 1000; i++) {
            User user = new User();
            user.setName("User" + i);
            user.setEmail("user" + i + "@example.com");
            mapper.insert(user);
        }

        // 統(tǒng)一提交
        session.commit();
    } catch (Exception e) {
        session.rollback();
        throw e;
    }
}

七、SqlSession與Mapper集成

SqlSession與Mapper接口的集成是MyBatis最常用的方式。

7.1 定義Mapper接口

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

7.2 Mapper XML映射文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mapper.UserMapper">

    <resultMap id="BaseResultMap" 
               type="com.example.entity.User">
        <id column="id" property="id" jdbcType="INTEGER"/>
        <result column="name" property="name" 
                jdbcType="VARCHAR"/>
        <result column="email" property="email" 
                jdbcType="VARCHAR"/>
    </resultMap>

    <select id="selectById" resultMap="BaseResultMap">
        SELECT id, name, email, age
        FROM t_user
        WHERE id = #{id}
    </select>

    <insert id="insert" parameterType="com.example.entity.User" 
            useGeneratedKeys="true" keyProperty="id">
        INSERT INTO t_user (name, email, age)
        VALUES (#{name}, #{email}, #{age})
    </insert>

</mapper>

7.3 通過(guò)SqlSession獲取Mapper

try (SqlSession session = factory.openSession()) {
    // 獲取Mapper代理對(duì)象
    UserMapper mapper = session.getMapper(UserMapper.class);

    //調(diào)用Mapper方法
    User user = mapper.selectById(1);

    //插入數(shù)據(jù)
    User newUser = new User();
    newUser.setName("李四");
    newUser.setEmail("lisi@example.com");
    mapper.insert(newUser);

    //提交事務(wù)
    session.commit();
}

7.4 MapperProxy工作原理

MyBatis通過(guò)JDK動(dòng)態(tài)代理為Mapper接口生成代理對(duì)象:

public class MapperProxy<T> implements InvocationHandler {

    private final SqlSession sqlSession;
    private final Class<T> mapperInterface;

    @Override
    public Object invoke(Object proxy, Method method, 
                        Object[] args) throws Throwable {
        // 如果是Object類(lèi)的方法,直接執(zhí)行
        if (Object.class.equals(method.getDeclaringClass())) {
            return method.invoke(this, args);
        }

        // 獲取Mapper方法
        final MapperMethod mapperMethod = 
            cachedMapperMethod(method);

        // 執(zhí)行Mapper方法
        return mapperMethod.execute(sqlSession, args);
    }
}

八、Executor執(zhí)行器詳解

Executor是SqlSession的核心組件,負(fù)責(zé)實(shí)際執(zhí)行SQL語(yǔ)句。

8.1 三種Executor類(lèi)型

// 默認(rèn)的Executor,每次執(zhí)行都會(huì)創(chuàng)建新的Statement
SqlSession session = factory.openSession(ExecutorType.SIMPLE);

特點(diǎn):簡(jiǎn)單直接,每次創(chuàng)建新Statement

適用場(chǎng)景:一般查詢(xún)、單條操作

// 重用Statement,減少創(chuàng)建開(kāi)銷(xiāo)
SqlSession session = factory.openSession(ExecutorType.REUSE);

特點(diǎn):重用Statement,減少創(chuàng)建開(kāi)銷(xiāo)

適用場(chǎng)景:執(zhí)行相同SQL多次

// 批量執(zhí)行SQL,性能最高
SqlSession session = factory.openSession(ExecutorType.BATCH);

特點(diǎn):批量執(zhí)行,性能最優(yōu)

適用場(chǎng)景:批量插入、更新

8.2 Executor對(duì)比表

Executor類(lèi)型性能Statement復(fù)用適用場(chǎng)景
SIMPLE????一般查詢(xún)
REUSE?????相同SQL多次執(zhí)行
BATCH??????批量操作

8.3 實(shí)戰(zhàn)示例

//BATCH執(zhí)行器批量插入示例
try (SqlSession session = factory.openSession(
    ExecutorType.BATCH)) {

    UserMapper mapper = session.getMapper(UserMapper.class);

    for (int i = 0; i < 1000; i++) {
        User user = new User();
        user.setName("User" + i);
        mapper.insert(user);
    }

    // 批量提交
    session.commit();
}

九、最佳實(shí)踐

9.1 SqlSession使用黃金法則

? 及時(shí)關(guān)閉 — 使用try-with-resources確保資源釋放
? 方法作用域 — SqlSession應(yīng)該在方法級(jí)別創(chuàng)建和關(guān)閉
? 線(xiàn)程獨(dú)立 — 每個(gè)線(xiàn)程使用獨(dú)立的SqlSession
? 事務(wù)控制 — 明確提交或回滾事務(wù)
? 異常處理 — 捕獲異常并回滾事務(wù)

9.2 Spring集成最佳實(shí)踐

在Spring中使用MyBatis時(shí),SqlSession由容器管理:

@Service
public class UserService {

    @Autowired
    private UserMapper userMapper;

    @Transactional
    public void createUser(User user) {
        // SqlSession由Spring管理,無(wú)需手動(dòng)關(guān)閉
        userMapper.insert(user);
    }
}

9.3 常見(jiàn)問(wèn)題排查

// 錯(cuò)誤示例
SqlSession session = factory.openSession();
User user = session.selectOne("...");
//忘記關(guān)閉 → 資源泄漏

//正確示例
try (SqlSession session = factory.openSession()) {
    User user = session.selectOne("...");
} // 自動(dòng)關(guān)閉
// 錯(cuò)誤示例
try (SqlSession session = factory.openSession()) {
    session.insert("...");
    // 忘記提交 → 數(shù)據(jù)未保存
}

//正確示例
try (SqlSession session = factory.openSession()) {
    session.insert("...");
    session.commit(); // 記得提交
}
//錯(cuò)誤示例
private SqlSession session = factory.openSession();

//正確示例
public User getUserById(Integer id) {
    try (SqlSession session = factory.openSession()) {
        return session.selectOne("...", id);
    }
}

十、總結(jié)

通過(guò)本文的學(xué)習(xí),我們深入了解了MyBatis會(huì)話(huà)模塊的核心內(nèi)容:

SqlSession接口 — 定義了所有數(shù)據(jù)庫(kù)操作方法
SqlSessionFactory — 負(fù)責(zé)創(chuàng)建和管理SqlSession實(shí)例
生命周期管理 — 方法級(jí)別創(chuàng)建,線(xiàn)程獨(dú)立使用
事務(wù)控制 — 支持手動(dòng)提交和自動(dòng)提交兩種模式
Mapper集成 — 通過(guò)動(dòng)態(tài)代理實(shí)現(xiàn)類(lèi)型安全操作
Executor類(lèi)型 — SIMPLE、REUSE、BATCH各有千秋

到此這篇關(guān)于MyBatis會(huì)話(huà)模塊詳解的文章就介紹到這了,更多相關(guān)MyBatis會(huì)話(huà)模塊內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

永济市| 巴楚县| 柳河县| 邵东县| 聊城市| 会东县| 磐石市| 万年县| 宽城| 增城市| 枣阳市| 错那县| 眉山市| 福泉市| 呼伦贝尔市| 通渭县| 西贡区| 石家庄市| 夏河县| 农安县| 乡城县| 泊头市| 襄垣县| 平罗县| 昆明市| 三明市| 都江堰市| 连云港市| 江阴市| 施甸县| 保定市| 新和县| 尼勒克县| 政和县| 万载县| 阿克苏市| 苗栗市| 海淀区| 惠东县| 舟曲县| 繁峙县|