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

Spring 數據訪問核心筆記(二):JdbcTemplate 深度解析、批量操作、存儲過程與 ORM 整合模式

     編輯:Java 相關知識

《Spring in Action》第四章筆記,聚焦 Spring JDBC 核心抽象:模板方法模式封裝固定流程、回調介面處理變化邏輯,詳解 JdbcTemplate 核心操作、批量更新、結果集映射、存儲過程調用、以及 Hibernate/iBatis/JDO 整合要點。

模板-回調設計模式

Spring 將 JDBC 固定流程(獲取連接、創建 Statement、事務控制、資源釋放、異常轉換)封裝於 JdbcTemplate,變化邏輯(SQL、參數綁定、結果整理)委派給回調介面:

  • PreparedStatementCreator:創建 PreparedStatement(含 SQL 與參數)。
  • PreparedStatementSetter:綁定參數值。
  • RowCallbackHandler:逐行處理 ResultSet(無返回值)。
  • RowMapper:將單行映射為領域對象(推薦,可返回 List)。
  • ResultSetExtractor:整個結果集提取單一結果(如聚合、分頁)。
  • CallableStatementCallback:處理存儲過程 CallableStatement。

JdbcTemplate 核心操作實戰

構造與線程安全

JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); // 線程安全,可作 Bean 注入
// 或繼承 JdbcDaoSupport,用 getJdbcTemplate() 獲取

更新操作(INSERT/UPDATE/DELETE)

// 簡單更新
jdbcTemplate.update("UPDATE user SET name=? WHERE id=?", "John", 1L);

// 批量更新:高效處理大量數據
List batchArgs = new ArrayList<>();
for (User u : users) batchArgs.add(new Object[]{u.getName(), u.getId()});
int[] counts = jdbcTemplate.batchUpdate("UPDATE user SET name=? WHERE id=?", batchArgs);

注意:execute() 無參數重載;帶參數更新請用 update(sql, args) 或 batchUpdate。

查詢操作與 RowMapper 最佳實踐

// 單行查詢
User user = jdbcTemplate.queryForObject(
    "SELECT id, name, email FROM user WHERE id=?", 
    new RowMapper() {
        public User mapRow(ResultSet rs, int rowNum) throws SQLException {
            User u = new User();
            u.setId(rs.getLong("id"));
            u.setName(rs.getString("name"));
            u.setEmail(rs.getString("email"));
            return u;
        }
    }, 1L);

// 多行查詢
List users = jdbcTemplate.query(
    "SELECT id, name, email FROM user WHERE active=1", 
    (rs, rowNum) -> new User(rs.getLong("id"), rs.getString("name"), rs.getString("email"))); // Java 8 Lambda

// 簡單值查詢
int count = jdbcTemplate.queryForObject("SELECT COUNT(*) FROM user", Integer.class);
String name = jdbcTemplate.queryForObject("SELECT name FROM user WHERE id=?", String.class, 1L);

存儲過程調用

jdbcTemplate.execute("{call ARCHIVE_USERS(?, ?)}", new CallableStatementCallback() {
    public Integer doInCallableStatement(CallableStatement cs) throws SQLException {
        cs.setInt(1, 2023);        // IN 參數
        cs.registerOutParameter(2, Types.INTEGER); // OUT 參數
        cs.execute();
        return cs.getInt(2);       // 返回 OUT 值
    }
});

進階抽象:SqlUpdate / MappingSqlQuery

將 SQL 操作封裝為可重用對象,近似 DAO 方法:

public class InsertUser extends SqlUpdate {
    public InsertUser(DataSource ds) {
        super(ds, "INSERT INTO user(name, email) VALUES(?, ?)");
        declareParameter(new SqlParameter("name", Types.VARCHAR));
        declareParameter(new SqlParameter("email", Types.VARCHAR));
        compile();
    }
    public int execute(String name, String email) {
        return update(new Object[]{name, email});
    }
}

優點:類型安全、可重用、隱藏 JDBC 細節。缺點:增加類數量,簡單項目用 JdbcTemplate 更直接。

自增主鍵獲取:DataFieldMaxValueIncrementer

抽象不同數據庫序列/自增機制:

  • MySQLMaxValueIncrementer:SELECT LAST_INSERT_ID()
  • OracleSequenceMaxValueIncrementer:序列 NEXTVAL
  • PostgreSQLSequenceMaxValueIncrementer
  • HsqlMaxValueIncrementer / DerbyMaxValueIncrementer
DataFieldMaxValueIncrementer inc = new MySQLMaxValueIncrementer(dataSource, "user");
long newId = inc.nextLongValue(); // 插入前獲取 ID,或插入後獲取

ORM 整合核心要點

ORM核心 FactoryBean模板類關鍵配置
HibernateLocalSessionFactoryBeanHibernateTemplatemappingDirectoryLocations 掃描 *.hbm.xml,不再需 hibernate.cfg.xml
iBatis 2.xSqlMapClientFactoryBeanSqlMapClientTemplateconfigLocation=sqlMap-config.xml,保留原配置檔
iBatis 1.3SqlMapFactoryBeanSqlMapTemplate類名 SqlMapXxx
JDOLocalPersistenceManagerFactoryBeanJdoTemplate較少用
TopLinkTopLinkFactoryBeanTopLinkTemplateOracle 產品

Hibernate 整合關鍵

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="mappingDirectoryLocations">
        <list><value>classpath:com/example/domain/</value></list>
    </property>
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
            <prop key="hibernate.show_sql">true</prop>
        </props>
    </property>
</bean>

<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
    <property name="sessionFactory" ref="sessionFactory"/>
</bean>

DAO 繼承 HibernateDaoSupport 或注入 HibernateTemplate,使用 HibernateCallback 執行複雜查詢/批量操作。

關鍵收穫

  • JdbcTemplate 封裝 JDBC 固定流程,回調介面分離變化邏輯,核心掌握 update/query/batchUpdate/RowMapper。
  • 批量操作用 batchUpdate(sql, List),效能遠超迴圈單條執行。
  • 結果集映射首選 RowMapper(Java 8 Lambda 極簡潔),避免舊版 RowCallbackHandler+RowMapperResultReader。
  • ORM 整合核心是配置對應 FactoryBean,統一事務、異常轉換、資源管理,DAO 層幾乎無 ORM 專用代碼。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved