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

MyBatis 入門實戰(一):從 Hibernate 遷移到 MyBatis 的核心配置與 CRUD 實作

     編輯:Java 綜合教學

MyBatis 入門實戰(一):從 Hibernate 遷移到 MyBatis 的核心配置與 CRUD 實作

MyBatis 是一款優秀的持久層框架,支援自訂 SQL、預存程序以及進階映射。相較於 Hibernate 的全自動 ORM 映射,MyBatis 採用半自動方式,雖然需要手寫 SQL,但擁有極高的靈活度與效能優化空間,非常適合新手入門,學習門檻相對較低。

為什麼選擇 MyBatis?從 Hibernate 遷移的心路歷程

筆者早期使用 Hibernate,深愛其 POJO 註解映射與 HQL 查詢的便利性——get(id)、save(entity)、delete(entity)、update(entity) 幾行代碼即可完成 CRUD。然而隨著專案規模增長,資料庫效能問題頻現,必須深入優化 SQL 時,Hibernate 的黑盒機制反而成為阻礙。

MyBatis 雖需手寫 SQL,但字段映射機制完善,寫 SQL 的過程反而能加深對資料庫的理解,掌握索引設計、執行計劃分析等核心技能。選型建議:大型專案、高併發、複雜查詢優先 MyBatis;中小型後台管理系統、查詢量不大者 Hibernate 仍具生產力優勢。當然,全專案統一使用 MyBatis 也是許多團隊的標準做法。

專案結構與依賴配置

工程結構圖

本範例未使用 Maven 管理依賴(後續 SSM 整合篇將引入),核心 JAR 包清單如下:

  • asm-3.3.1.jar
  • cglib-2.2.2.jar
  • commons-logging-1.1.1.jar
  • javassist-3.17.1-GA.jar
  • log4j-1.2.17.jar / log4j-api-2.0-beta9.jar / log4j-core-2.0-beta9.jar
  • mybatis-3.2.3.jar
  • mysql-connector-java-5.1.7-bin.jar
  • slf4j-api-1.7.5.jar / slf4j-log4j12-1.7.5.jar

核心配置文件:SqlMapConfig.xml

此文件是 MyBatis 與資料庫的橋樑,包含資料源、事務管理器、Mapper 映射註冊等核心配置:

<?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>
<!-- 整合 Spring 後 environments 配置將廢除 -->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8" />
<property name="username" value="root" />
<property name="password" value="root" />
</dataSource>
</environment>
</environments>

<!-- 配置 mapper 映射文件 -->
<mappers>
<mapper resource="sqlmap/User.xml"/>
</mappers>
</configuration>

Mapper 映射文件:User.xml

針對 User 實體的 SQL 定義,展示基本 CRUD 與參數映射細節:

<?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">
<!-- namespace 命名空間:使用 Mapper 動態代理時需配置為 Mapper 接口全限定名 -->
<mapper namespace="test">

<!-- 根據 ID 查詢單條記錄 -->
<select id="findUserById" parameterType="int" resultType="com.mybatis001.bean.User">
SELECT * FROM USER WHERE id = #{id}
</select>

<!-- 模糊查詢用戶列表 -->
<select id="findUserList" parameterType="java.lang.String" resultType="com.mybatis001.bean.User">
select * from user where name like '%${value}%'
</select>

<!-- 新增用戶,回填自增主鍵 -->
<insert id="insertUser" parameterType="com.mybatis001.bean.User">
<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
select LAST_INSERT_ID()
</selectKey>
insert into user(name,age,sex) values(#{name},#{age},#{sex})
</insert>

<!-- 刪除用戶 -->
<delete id="deleteUser" parameterType="int">
delete from user where id=#{id}
</delete>

<!-- 更新用戶 -->
<update id="updateUser" parameterType="com.mybatis001.bean.User">
update user set name=#{name},age=#{age},sex=#{sex} where id=#{id}
</update>

</mapper>

關鍵點解析:

  • #{}:預編譯佔位符,防止 SQL 注入,參數名可任意
  • ${}:字串拼接,無法防注入,動態表名、排序欄位等場景必須使用
  • <selectKey>:插入後回填自增主鍵到實體對象
  • parameterType/resultType:輸入輸出類型映射,屬性名與查詢欄位名一致才能自動映射

實體類與 DAO 層實作

User.java - 標準 POJO,包含 id、name、age、sex 四個屬性及 Getter/Setter

UserDao.java - 定義資料訪問接口:

public interface UserDao {
    User findUserById(int id) throws Exception;
    List<User> findUserList(String name) throws Exception;
    Integer insertUser(User user) throws Exception;
    void deleteUser(int id) throws Exception;
    void updateUser(User user) throws Exception;
}

UserDaoImpl.java - 基於 SqlSessionFactory 的原生實作:

public class UserDaoImpl implements UserDao {
    private SqlSessionFactory sqlSessionFactory;
    
    public UserDaoImpl(SqlSessionFactory sqlSessionFactory) {
        this.sqlSessionFactory = sqlSessionFactory;
    }
    
    @Override
    public User findUserById(int id) throws Exception {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // statement 格式:namespace.id
        User user = sqlSession.selectOne("test.findUserById", id);
        sqlSession.close();
        return user;
    }
    
    @Override
    public List<User> findUserList(String name) throws Exception {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        List<User> userList = sqlSession.selectList("test.findUserList", name);
        sqlSession.close();
        return userList;
    }
    
    @Override
    public Integer insertUser(User user) throws Exception {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        int lastUserId = sqlSession.insert("test.insertUser", user);
        sqlSession.commit();
        sqlSession.close();
        return lastUserId;
    }
    
    @Override
    public void deleteUser(int id) throws Exception {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        sqlSession.delete("test.deleteUser", id);
        sqlSession.commit();
        sqlSession.close();
    }
    
    @Override
    public void updateUser(User user) throws Exception {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        sqlSession.update("test.updateUser", user);
        sqlSession.commit();
        sqlSession.close();
    }
}

JUnit 整合測試

public class UserDaoImplTest {
    private SqlSessionFactory sqlSessionFactory;
    
    @Before
    public void setUp() throws Exception {
        String resource = "SqlMapConfig.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    }
    
    @Test
    public void testFindUserById() throws Exception {
        UserDao userDao = new UserDaoImpl(sqlSessionFactory);
        User user = userDao.findUserById(1001);
        List<User> userList = userDao.findUserList("lee");
        userList.forEach(System.out::println);
    }
    
    @Test
    public void insertUser() throws Exception {
        UserDao userDao = new UserDaoImpl(sqlSessionFactory);
        userDao.insertUser(new User("nathan.lee.salvatore", 18, "男"));
        userDao.insertUser(new User("nathan", 22, "男"));
        userDao.insertUser(new User("leechenxiang", 20, "男"));
        userDao.insertUser(new User("李晨翔", 19, "男"));
    }
    
    @Test
    public void deleteUser() throws Exception {
        UserDao userDao = new UserDaoImpl(sqlSessionFactory);
        userDao.deleteUser(1013);
    }
    
    @Test
    public void updateUser() throws Exception {
        UserDao userDao = new UserDaoImpl(sqlSessionFactory);
        User user = new User("李斯涵", 1, "女");
        user.setId(1001);
        userDao.updateUser(user);
    }
}

完整代碼已上傳 GitHub:https://github.com/leechenxiang/mybatis001

下一篇將深入探討 MyBatis 動態 SQL、類型別名、Mapper 掃描等進階特性,敬請期待。

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