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

MyBatis 核心功能全景指南:從基礎 CRUD 到 Spring 整合、SqlSessionFactory 原理解析

     編輯:Java 相關知識

MyBatis 核心架構速覽

MyBatis 採用「配置驅動」架構,核心組件協作流程:

配置文件(mybatis-config.xml) 
  → SqlSessionFactoryBuilder 
  → SqlSessionFactory (單例,線程安全) 
  → SqlSession (非線程安全,請求級) 
  → Mapper 接口代理 / 直接執行 SQL
  → 結果映射 (resultType/resultMap)
  → 返回實體對象

1. 基礎映射方式對比

方式一:注解映射(簡單場景)

public interface BlogMapper {
    @Select("select * from t_blog where id = #{id}")
    Blog selectBlog(int id);
}

方式二:XML 映射(複雜場景推薦)

<mapper namespace="com.example.BlogMapper">
  <select id="selectBlog" parameterType="int" resultType="Blog">
    select * from t_blog where id = #{id}
  </select>
</mapper>

方式三:API 直接調用(動態場景)

Blog blog = session.selectOne("com.example.BlogMapper.selectBlog", 101);

2. Spring 整合最佳實踐

XML 配置方式

<!-- 數據源 -->
<bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource">
  <property name="jdbcUrl" value="${jdbc.url}"/>
  <property name="username" value="${jdbc.username}"/>
  <property name="password" value="${jdbc.password}"/>
</bean>

<!-- SqlSessionFactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
  <property name="dataSource" ref="dataSource"/>
  <property name="mapperLocations" value="classpath:mapper/*.xml"/>
  <property name="typeAliasesPackage" value="com.example.model"/>
</bean>

<!-- 掃描 Mapper 接口 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
  <property name="basePackage" value="com.example.mapper"/>
  <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>

業務層注入使用

@Service
public class BlogServiceImpl implements BlogService {
    @Autowired
    private BlogMapper blogMapper; // 自動注入 Mapper 代理
    
    public void doSomething(int blogId) {
        Blog blog = blogMapper.selectBlog(blogId);
        // 事務由 Spring 管理(@Transactional)
    }
}

Spring Boot 簡化配置

@MapperScan("com.example.mapper")
@SpringBootApplication
public class Application { ... }

// application.yml
mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.example.model
  configuration:
    map-underscore-to-camel-case: true
    cache-enabled: true

3. SqlSessionFactory 深度解析

構建方式

// 1. 從輸入流構建(最常用)
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);

// 2. 指定環境
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is, "production");

// 3. 覆蓋配置屬性
Properties props = new Properties();
props.setProperty("jdbc.url", "jdbc:mysql://prod:3306/db");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is, props);

// 4. 從 Configuration 對象構建(程序化配置)
Configuration config = new Configuration();
config.setEnvironment(new Environment("dev", new JdbcTransactionFactory(), dataSource));
config.addMapper(BlogMapper.class);
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(config);

單例模式實現

public class SqlSessionFactoryHolder {
    private static final SqlSessionFactory FACTORY;
    
    static {
        try (InputStream is = Resources.getResourceAsStream("mybatis-config.xml")) {
            FACTORY = new SqlSessionFactoryBuilder().build(is);
        } catch (IOException e) {
            throw new ExceptionInInitializerError(e);
        }
    }
    
    public static SqlSessionFactory getSqlSessionFactory() {
        return FACTORY;
    }
}

4. 核心配置文件結構詳解

<configuration>
  <properties resource="jdbc.properties"/>           <!-- 外部屬性 -->
  <settings>                                        <!-- 運行時行為 -->
    <setting name="mapUnderscoreToCamelCase" value="true"/>
    <setting name="cacheEnabled" value="true"/>
    <setting name="lazyLoadingEnabled" value="true"/>
  </settings>
  <typeAliases>                                     <!-- 類型別名 -->
    <package name="com.example.model"/>
  </typeAliases>
  <typeHandlers>                                    <!-- 類型處理器 -->
    <typeHandler handler="com.example.handler.JsonTypeHandler"/>
  </typeHandlers>
  <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>

數據源類型對比

類型特點適用場景
UNPOOLED每次打開/關閉連接,無池化簡單應用、測試環境
POOLED內置連接池,配置豐富生產環境標準選擇
JNDI容器管理數據源(Tomcat/JBoss/WebLogic)Java EE 容器部署

事務管理器類型

  • JDBC:使用 JDBC 原生提交/回滾,MyBatis 管理事務邊界
  • MANAGED:不提交/回滾,交給容器(Spring/JTA)管理,需設 closeConnection="false"

5. SqlSession 核心 API 與執行類型

獲取 SqlSession 的多種方式

// 默認:事務不自動提交,連接來自配置數據源,SIMPLE 執行器
SqlSession session = factory.openSession();

// 顯式控制
SqlSession session = factory.openSession(ExecutorType.REUSE);     // 復用預處理語句
SqlSession session = factory.openSession(ExecutorType.BATCH);     // 批量更新
SqlSession session = factory.openSession(true);                   // 自動提交
SqlSession session = factory.openSession(Connection conn);        // 使用外部連接
SqlSession session = factory.openSession(TransactionIsolationLevel.READ_COMMITTED);

ExecutorType 三種模式

類型特點適用場景
SIMPLE每條語句創建新 PreparedStatement通用場景,默認
REUSE復用 PreparedStatement高頻重複 SQL,減少解析開銷
BATCH批量執行 update/insert/delete大批量寫入,需手動 flushStatements()

核心 CRUD 方法

<T> T selectOne(String statement, Object parameter)
<E> List<E> selectList(String statement, Object parameter)
<K,V> Map<K,V> selectMap(String statement, Object parameter, String mapKey)
int insert(String statement, Object parameter)
int update(String statement, Object parameter)
int delete(String statement, Object parameter)
// Mapper 接口方式(推薦)
Mapper mapper = session.getMapper(Mapper.class);
mapper.insert(entity);

6. 映射文件核心要點

resultType vs resultMap

  • resultType:簡單映射,列名=屬性名(或開啟駝峰轉換)
  • resultMap:複雜映射(列名不匹配、關聯對象、嵌套結果、構造方法注入)
  • 二者互斥,不可同時指定

Insert 主鍵回填

<insert id="insertBlog" parameterType="Blog" useGeneratedKeys="true" keyProperty="id">
  insert into t_blog(title, content, owner) values(#{title}, #{content}, #{owner})
</insert>

模糊查詢正確寫法

<!-- 錯誤:LIKE "%"#{title}"%" -->
<!-- 正確:CONCAT 或字符串拼接 -->
<select id="fuzzyQuery" resultType="Blog" parameterType="string">
  select * from t_blog where title LIKE CONCAT('%', #{title}, '%')
</select>

7. 完整示例代碼結構

com.example
├── model
│   └── Blog.java                    // 實體類
├── mapper
│   ├── BlogMapper.java              // 接口(含注解映射)
│   └── BlogMapper.xml               // XML 映射
├── service
│   └── BlogServiceImpl.java         // 業務層
├── test
│   ├── TestXmlMapper.java           // XML 映射測試
│   ├── TestAnnotationMapper.java    // 注解映射測試
│   └── TestApiDirect.java           // API 直接調用測試
└── util
    └── MyBatisUtil.java             // SqlSessionFactory 工具

8. 建表語句

CREATE TABLE t_blog (
  id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
  title VARCHAR(255) DEFAULT NULL,
  content VARCHAR(255) DEFAULT NULL,
  owner VARCHAR(50) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

總結

MyBatis 核心功能體系包含:多樣的映射方式(注解/XML/API)、無縫 Spring 整合、靈活的 SqlSessionFactory 構建、豐富的配置體系(屬性、設置、類型別名、環境、映射器)、多模式 SqlSession(SIMPLE/REUSE/BATCH)、強大的結果映射(resultType/resultMap/主鍵回填)。掌握這些核心知識點,配合動態 SQL、緩存、插件機制等進階特性,能構建出高性能、可維護的持久層架構。

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