首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

MyBatis Mapper 與 DAO 開發實戰:從入門到最佳實踐

     編輯:MySQL 綜合教學

MyBatis 核心優勢

MyBatis(前身 iBatis)是優秀的 Java 持久層框架,本質上是對 JDBC 的深度封裝。開發者專注於 SQL 本身,無需處理驅動註冊、連接創建、參數綁定、結果集解析等繁瑣流程代碼。

MyBatis 支援 XML 與註解兩種方式配置 Statement,將執行結果自動映射為 Java 對象,大幅降低數據庫開發複雜度。

MyBatis 架構圖


快速入門:CRUD 完整示例

1. 環境依賴

<dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.13</version></dependency>
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.33</version></dependency>

2. 全局配置文件

<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/test?useSSL=false&serverTimezone=UTC"/>
        <property name="username" value="root"/>
        <property name="password" value="123456"/>
      </dataSource>
    </environment>
  </environments>
  <mappers>
    <mapper resource="mybatis/mapper/UserDAO.xml"/>
  </mappers>
</configuration>

3. 實體類 (POJO)

public class User {
    private Integer id;
    private String name;
    private String password;
    // 構造器、Getter/Setter、toString 省略
}

4. Mapper 映射文件 (UserDAO.xml)

<mapper namespace="com.fq.mybatis.UserDAO">
  <select id="selectUserById" parameterType="java.lang.Integer" resultType="com.fq.domain.User">
    SELECT * FROM user WHERE id = #{id}
  </select>

  <select id="selectUserByName" parameterType="java.lang.String" resultType="com.fq.domain.User">
    SELECT * FROM user WHERE name LIKE '%${value}%'
  </select>

  <insert id="insertUser" parameterType="com.fq.domain.User" useGeneratedKeys="true" keyProperty="id">
    INSERT INTO user(name, password) VALUES(#{name}, #{password})
  </insert>

  <update id="updateUserById" parameterType="com.fq.domain.User">
    UPDATE user SET name = #{name}, password = #{password} WHERE id = #{id}
  </update>

  <delete id="deleteUserById" parameterType="java.lang.Integer">
    DELETE FROM user WHERE id = #{id}
  </delete>
</mapper>
屬性說明
namespace命名空間,隔離 SQL,Mapper 接口模式下需與接口全限定名一致
parameterType輸入參數類型,MyBatis 通過 OGNL 解析對象屬性
resultType輸出映射類型,將查詢結果每行映射為指定類型

5. 原始 DAO 開發模式(不推薦)

手寫接口與實現類,代碼中硬編碼 Statement ID,維護成本高:

public class UserDAOImpl implements UserDAO {
    private SqlSessionFactory factory;
    public UserDAOImpl(SqlSessionFactory factory) { this.factory = factory; }
    
    @Override
    public User selectUserById(Integer id) {
        SqlSession session = factory.openSession();
        try {
            return session.selectOne("namespace.selectUserById", id);
        } finally {
            session.close();
        }
    }
}

6. Mapper 接口映射開發(官方推薦)

僅定義接口,MyBatis 根據命名規約動態生成代理實現:

public interface UserDAO {
    User selectUserById(Integer id);
    List<User> selectUserByName(String name);
    void insertUser(User user);
    void updateUserById(User user);
    void deleteUserById(Integer id);
}

映射規約(必須遵守):
1. Mapper XML 的 namespace = 接口全限定名
2. Statement id = 接口方法名
3. parameterType/resultType = 方法參數/返回類型

客戶端調用極簡:

SqlSession session = factory.openSession();
UserDAO dao = session.getMapper(UserDAO.class);
User user = dao.selectUserById(1);  // 無硬編碼,類型安全
session.close();

進階映射技巧

參數傳遞方式

場景Mapper 寫法接口定義
單一簡單類型WHERE id = #{id} 或 #{value}User selectById(Integer id)
多個簡單類型UPDATE user SET name=#{1}, pwd=#{2} WHERE id=#{0}void update(Integer id, String name, String pwd)
POJO 對象WHERE name=#{name} AND pwd=#{password}User selectByUser(User user)
Map 集合WHERE name=#{name} AND pwd=#{password}User selectByMap(Map<String,Object> map)

#{ } vs ${ } 核心區別:
#{ }:預編譯佔位符,自動類型轉換,防止 SQL 注入。
${ }:字符串直接拼接,不進行類型轉換,用於動態表名、列名、排序字段等無法使用預編譯的場景(需自行防注入)。

結果映射

簡單類型

<select id="selectUserCount" parameterType="String" resultType="java.lang.Integer">
  SELECT count(*) FROM user WHERE name LIKE '%${value}%'
</select>

要求查詢結果僅一行一列,自動映射首列值。

POJO / List<POJO>

  • 單對象:selectOne,結果必須唯一
  • 列表:selectList,返回 List<User> 或 Set<User>

Map 結構輸出

<select id="selectUserLikeName" resultType="java.util.Map">
  SELECT * FROM user WHERE name LIKE '%${value}%'
</select>

返回 List<Map<String,Object>>,鍵為列名,值為列值。

resultMap:字段與屬性不一致時的映射

<resultMap id="userMap" type="com.fq.domain.User">
  <id column="user_id" property="id"/>
  <result column="user_name" property="name"/>
  <result column="user_password" property="password"/>
</resultMap>

<select id="selectUserByName" parameterType="String" resultMap="userMap">
  SELECT id AS user_id, name AS user_name, password AS user_password FROM user WHERE name = #{name}
</select>
標籤用途
<id>結果集唯一標識(主鍵),優化嵌套查詢性能
<result>普通列映射
columnSQL 查詢列名(或別名)
propertyPOJO 屬性名

最佳實踐總結

  1. 優先使用 Mapper 接口模式,減少樣板代碼,獲得類型安全與 IDE 重構支持
  2. SQL 與 Java 代碼分離,便於 DBA 優化與版本管理
  3. 善用 #{ } 防注入,僅在動態 DDL 元素(表名、列名、排序)使用 ${ }
  4. SqlSession 線程不安全,務必作為方法局部變量使用
  5. 配置日誌系統(Logback/Log4j2),開發調試時輸出 SQL 與參數,排查問題事半功倍

Logback 配置示例

<configuration>
  <property name="logRoot" value="/data/logs"/>
  <property name="pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{0} - %msg%n"/>
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder><pattern>${pattern}</pattern></encoder>
  </appender>
  <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
      <fileNamePattern>${logRoot}/mybatis-demo.%d{yyyy-MM-dd}.log</fileNamePattern>
      <maxHistory>30</maxHistory>
    </rollingPolicy>
    <encoder><pattern>${pattern}</pattern></encoder>
  </appender>
  <root level="DEBUG">
    <appender-ref ref="STDOUT"/>
    <appender-ref ref="FILE"/>
  </root>
</configuration>
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved