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

Spring + SpringMVC + Druid + MyBatis 企業級後端架構實戰:避坑指南與最佳實踐

     編輯:Java 綜合教學

架構演進:從 JPA 到 MyBatis 的技術選型思考

兩個月前團隊基於 Spring + SpringMVC + Druid + JPA(Hibernate) 搭建了一套穩健的後端框架,經過項目組打磨已趨成熟。近期為了探索更靈活的 SQL 控制能力,嘗試將持久層遷移至 MyBatis。作為接觸 Hibernate 更早的開發者,我發現兩大 ORM 框架核心思想相通,但 MyBatis 獨有的 ResultMap 機制支持極致的 SQL 調優,這正是我們遷移的核心動力。雖然 Hibernate 在社區活躍度、版本迭代、工具生態上略勝一籌,但 MyBatis 的半自動映射特性更適合複雜查詢場景。

項目地址:https://git.oschina.net/LanboEx/sdm

整體架構設計

架構圖

  • Controller 層:接收前端參數、校驗、調用 Service、響應視圖/JSON
  • Service 層:接口與實現分離,組織業務邏輯、事務邊界、異常處理
  • DAO/Mapper 層:MyBatis Mapper 接口 + XML 映射,支持工具自動生成

代碼生成採用 org.mybatis.generator 插件,可自動生成 PO、Mapper 接口、XML 映射文件,大幅提升開發效率。

實戰踩坑記錄與解決方案

坑 1:MapperScannerConfigurer 提前初始化導致屬性佔位符解析失效

現象

配置 sqlSessionFactory 直接引用 bean 時,Spring 無法解析 ${jdbc.username} 等佔位符,導致數據源初始化失敗。

根因

MapperScannerConfigurer 在 Bean 定義解析階段初始化,此時 PropertyPlaceholderConfigurer 尚未替換佔位符,導致表達式作為字面值傳遞。

解決

改用 sqlSessionFactoryBeanName 指定 bean 名稱,延遲初始化至 Bean 創建階段:

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
  <property name="basePackage" value="com.rambo.sdm.dao.inter"/>
  <property name="sqlSessionFactoryBeanName" value="sessionFactory"/>
</bean>

坑 2:DAO 層主鍵自動生成策略配置繁瑣

問題

MyBatis Generator 生成的映射文件中,主鍵生成策略(自增/UUID)需手動配置,易遺漏、易出錯。

XML 級配置

<insert id="insert" parameterType="UserPO">
  <selectKey keyProperty="uuid" resultType="String" order="BEFORE">
    SELECT REPLACE(UUID(),'-','') AS UUID
  </selectKey>
  ...
</insert>

Generator 統一配置(推薦)

<table tableName="user" domainObjectName="UserPO">
  <generatedKey column="uuid" sqlStatement="SELECT REPLACE(UUID(),'-','') UUID FROM DUAL"/>
</table>

注意:SQL 寫死導致數據庫移植性下降,跨數據庫項目需謹慎評估。

坑 3:Maven 編譯未將 XML 文件輸出到 target/classes

現象

運行報錯 BindingException: Invalid bound statement (not found),實為 Mapper XML 未編譯到輸出目錄。

解決

在 pom.xml <resources> 節點添加兩個 resource 目錄:

<resources>
  <resource>
    <directory>src/main/java</directory>
    <includes><include>**/*.xml</include></includes>
    <filtering>true</filtering>
  </resource>
  <resource>
    <directory>src/main/resources</directory>
    <includes>
      <include>**/*.xml</include>
      <include>**/*.properties</include>
    </includes>
    <filtering>true</filtering>
  </resource>
</resources>

坑 4:Jetty 插件啟動觸發 MyBatis Generator 重複執行

現象

jetty:run 時 Generator 插件先運行,配置文件內容追加而非覆蓋,導致 Result Maps collection already contains value 錯誤。

根因

Generator 插件綁定到 generate-sources 階段,Jetty 啟動觸發完整構建生命週期。插件邏輯:Java 文件存在則跳過,但 XML 文件追加內容。

規避

  • 將 Generator 移至獨立 Maven Profile,僅手動觸發:mvn mybatis-generator:generate -Pgenerator
  • 或配置 <overwrite>true</overwrite>(需插件版本支持)

核心配置文件速覽

web.xml 關鍵點

  • ContextLoaderListener 初始化 Spring 容器
  • DispatcherServlet 配置 SpringMVC,攔截 /,REST 風格
  • 字符編碼過濾器 CharacterEncodingFilter 設置 UTF-8
  • Druid StatViewServlet 監控頁面配置

pom.xml 依賴亮點

  • Spring 4.x + SpringMVC 4.x
  • MyBatis 3.4+ + MyBatis-Spring 1.3+
  • Druid 1.1.10 高性能連接池 + 監控
  • MySQL Connector/J + Jackson JSON 處理
  • MyBatis Generator Maven Plugin 代碼生成

總結與建議

  1. 技術選型務實:MyBatis 適合複雜 SQL、性能敏感場景;JPA 適合領域模型豐富、標準 CRUD 為主的業務
  2. Generator 納入構建流程:獨立 Profile 管理,避免污染常規構建
  3. 主鍵策略統一:團隊規範制定,減少手動配置風險
  4. 資源文件輸出檢查:Maven Resources Plugin 配置作為項目模板標準化
  5. 持續重構:架構演進伴隨業務增長,定期回顧技術債

這套方案經過實戰驗證,穩定支撐業務增長。開源地址歡迎 Star、Fork、Issue 交流,共同完善。

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