日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

Spring JDBC-使用Spring JDBC访问数据库

發(fā)布時間:2025/3/21 javascript 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring JDBC-使用Spring JDBC访问数据库 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

  • 概述
  • 使用Spring JDBC
  • 基本的數(shù)據(jù)操作
    • 更改數(shù)據(jù)
    • 返回數(shù)據(jù)庫表的自增主鍵值
    • 批量更改數(shù)據(jù)
    • 查詢數(shù)據(jù)
    • 使用RowCallbackHandler處理結(jié)果集
    • 使用RowMapperT處理結(jié)果集
    • RowCallbackHandler和RowMapperT的比較
    • 查詢單值數(shù)據(jù)
    • 調(diào)用存儲過程3種方式
  • 示例源碼

概述

Spring JDBC是Spring所提供的持久層技術(shù),它的主要目的降低JDBC API的使用難度,以一種更直接、更簡潔的方式使用JDBC API。

Spring JDBC中,僅僅需要做那些和業(yè)務(wù)相關(guān)的DML操作的事兒而將獲取資源、Statement創(chuàng)建、釋放資源以及異常處理等繁雜乏味的工作交給Spring JDBC.


使用Spring JDBC

Spring JDBC通過模板回調(diào)機制大大降低了使用JDBC的復(fù)雜度。

一般情況下,都是在DAO類中使用JdbcTemplate,JdbcTemplate在XML配置文件中后,在DAO中直接注入引用JdbcTemplate即可.

我們看一個配置文件的例子

<?xml version="1.0" encoding="UTF-8" ?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><!-- 掃描類包,將標(biāo)注Spring注解的類自動轉(zhuǎn)化Bean,同時完成Bean的注入 --><context:component-scan base-package="com.xgj.dao.demo"/><!-- 不使用context命名空間,則需要定義Bean<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations" value="classpath:spring/jdbc.properties" /> </bean> --><!-- 使用context命名空間,同上面的Bean等效.在xml文件中配置數(shù)據(jù)庫的properties文件 --><context:property-placeholder location="classpath:spring/jdbc.properties" /><bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"p:driverClassName="${jdbc.driverClassName}"p:url="${jdbc.url}"p:username="${jdbc.username}"p:password="${jdbc.password}" /><!-- 配置Jdbc模板 --><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"p:dataSource-ref="dataSource" /></beans>

在Spring配配置那文件中配置DAO一般分為4個步驟

  • 定義DataSource

  • 定義JdbcTemplate

  • 聲明一個抽象的Bean,以便所有的DAO復(fù)用配置JdbcTemplate屬性的配置(使用注解的方式更加方便)

  • 配置具體的DAO(使用注解的方式更加方便)


其中JdbCTemplate有幾個屬性可以控制底層JDBC API的屬性。

  • queryTimeout 查詢數(shù)據(jù)的最大超時時間,默認(rèn)為0 ,表示使用底層JDBC驅(qū)動程序的默認(rèn)設(shè)置

  • fetchSize:設(shè)置底層的ResultSet每次從數(shù)據(jù)庫返回的行數(shù),該屬性對程序的性能影響較大,如果設(shè)置過大,因為一次性載入的數(shù)據(jù)都會放到內(nèi)存中,所以內(nèi)存消耗會很大,反之設(shè)置的過小,從數(shù)據(jù)庫讀取的次數(shù)將增大,也會影響性能。 默認(rèn)為0 ,表示使用底層JDCB驅(qū)動程序的默認(rèn)設(shè)置。 Oracle驅(qū)動程序的fetchsize的默認(rèn)值為10

  • maxRows:設(shè)置底層的ResutlSet從數(shù)據(jù)庫返回的最大行數(shù),默認(rèn)為0 ,表示使用底層JDBC驅(qū)動程序默認(rèn)的設(shè)置

  • ignoreWarnings :是否忽略SQL的告警信息。默認(rèn)為true,即所有的告警信息都記錄到日志中,如果設(shè)置為false,則JdbcTemplate將拋出SQLWarningException


  • 基本的數(shù)據(jù)操作

    數(shù)據(jù)庫的增刪改查(CRUD)及存儲過程調(diào)用是最常見的數(shù)據(jù)庫操作,JdbcTemplate提供了眾多的方法,通過JdbcTemplate可以用簡單的方法完成這些數(shù)據(jù)操作。


    下面我們以示例來實際演示下這些操作

    更改數(shù)據(jù)

    JdbcTemplate提供了若干個update方法,允許對數(shù)據(jù)表記錄記錄進行更改和刪除操作。

    首先我們定義一個抽象的DAO基類, BaseDao。 其中暫時我們只封裝了注入JDBC的操作(擴展的話可以將分頁等通用的功能抽取到BaseDao中等)

    package com.xgj.dao.basicOperation;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate;public abstract class BaseDao {public JdbcTemplate jdbcTemplate;// 注入JdbcTemplate實例@Autowiredpublic void setJdbcTemplate(JdbcTemplate jdbcTemplate) {this.jdbcTemplate = jdbcTemplate;} }

    然后我們編寫DAO層的代碼,簡單旗艦,直接將DAO定義成了類。一般來講將DAO層編寫成接口更合適。

    package com.xgj.dao.basicOperation.insertUpdateAndDelete;import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.List;import org.springframework.jdbc.core.BatchPreparedStatementSetter; import org.springframework.stereotype.Repository;import com.xgj.dao.demo.BaseDao;/*** * * @ClassName: ArtisanDao* * @Description: @Repository標(biāo)注的DAO* * @author: Mr.Yang* * @date: 2017年9月18日 下午4:19:06*/@Repository public class ArtisanDao extends BaseDao {private static final String sql = "insert into artisan_user(user_name,password) values(?,?)";/*** * * @Title: addSingleArtisan* * @Description: 增加一個Artisan* * @param artisan* * @return: void*/public void addSingleArtisan(Artisan artisan) {jdbcTemplate.update(sql, artisan.getUserName(), artisan.getPassword());System.out.println("insert successfully");}}

    由于JdbcTemplate在內(nèi)部通過PreparedStatement執(zhí)行SQL語句,所以可以綁定參數(shù)的SQL語句,每個“?”占位符可以接受一個參數(shù)。

    盡量使用可綁定參數(shù)的SQL語句,以便數(shù)據(jù)庫可以復(fù)用SQL的執(zhí)行計劃,提高數(shù)據(jù)庫的執(zhí)行效率。 此外,應(yīng)該在DAO使用類級別的靜態(tài)常量(final static)定義SQL字符串,不應(yīng)該在方法內(nèi)部聲明SQL字符串變量,以提高JVM的內(nèi)存使用效率。

    在通過public int update(String sql, Object... args) throws DataAccessException 方法為SQL語句的占位符綁定參數(shù)時,并沒有顯示的指定對應(yīng)字段的數(shù)據(jù)類型,此時,Spring直接讓PreparedStatement根據(jù)參數(shù)的類型進行“猜測”。 有一種更好的做法是使用public int update(String sql, Object[] args, int[] argTypes) throws DataAccessException顯示指定每個占位符所對英的字段數(shù)據(jù)類型,這樣就可以保證類型安全,當(dāng)參數(shù)值為null時,這種形式提供了更好的支持。

    以下代碼僅為演示

    // 使用該類中的常量屬性定義參數(shù)類型 import java.sql.Type ....jdbcTemplate,update(sql, new Object[]{..} ,new int[]{Types.VARCHAR2...});....

    配置文件如下(以下的幾個操作都加載這個配置文件)

    <?xml version="1.0" encoding="UTF-8" ?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><!-- 掃描類包,將標(biāo)注Spring注解的類自動轉(zhuǎn)化Bean,同時完成Bean的注入 --><context:component-scan base-package="com.xgj.dao.basicOperation" /><!-- 不使用context命名空間,則需要定義Bean <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations" value="classpath:spring/jdbc.properties" /> </bean> --><!-- 使用context命名空間,同上面的Bean等效.在xml文件中配置數(shù)據(jù)庫的properties文件 --><context:property-placeholder location="classpath:spring/jdbc.properties" /><bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"destroy-method="close" p:driverClassName="${jdbc.driverClassName}"p:url="${jdbc.url}" p:username="${jdbc.username}" p:password="${jdbc.password}" /><!-- 配置Jdbc模板 --><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"p:dataSource-ref="dataSource" /></beans>

    測試類

    package com.xgj.dao.basicOperation.insertUpdateAndDelete;import java.util.ArrayList; import java.util.List;import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;public class ArtisanDaoTest {public static void main(String[] args) {// 啟動Spring 容器ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:com/xgj/dao/basicOperation/basicOperation.xml");Artisan artisan = ctx.getBean("artisan", Artisan.class);artisan.setUserName("Artisan");artisan.setPassword("987654");ArtisanDao artisanDao = ctx.getBean("artisanDao", ArtisanDao.class);// 調(diào)用目標(biāo)方法artisanDao.addSingleArtisan(artisan); }

    除了上述兩個update方法外,JdbcTemplate還提供了以下幾個功能相似的重載方法


    • public int update(final String sql) 為不帶占位符的SQL語句提供的便利方法

    • public int update(String sql, PreparedStatementSetter pss) PreparedStatementSetter 是一個回調(diào)接口,它定義了一個setValues(PreparedStatement ps)接口方法 ,如下所示

    public void addStudent(Student student){jdbcTemplate.update(sql,new PreparedStatementSetter (){public void setValues(PreparedStatement ps) throws SQLException{ps.setString(1,student.getName());ps.setString(2,student,getSex());} });}

    PreparedStatement綁定參數(shù)時,參數(shù)索引從1開始,而非0開始。 第一個參數(shù)索引為1,第二個參數(shù)索引為2,依次類推。

    當(dāng)然了,還有其他方法 ,需要指出的是,在實際用用中,應(yīng)該優(yōu)先考慮不帶回調(diào)接口的JdbcTemplate方法。沒有必要使用那些帶有回調(diào)接口的方法,因為Spring會在內(nèi)部自動創(chuàng)建這些回調(diào)實例。


    返回數(shù)據(jù)庫表的自增主鍵值

    舉個例子 ORACLE數(shù)據(jù)庫

    com.xgj.dao.transaction.annotationTrans.dao.impl.StudentDaoImpl.java

    @Overridepublic void addStudent(final Student student) {// 這里采用和addTeacher不同的方式,輸出插入數(shù)據(jù)庫的主鍵IDKeyHolder keyHolder = new GeneratedKeyHolder();PreparedStatementCreator preparedStatementCreator = new PreparedStatementCreator() {@Overridepublic PreparedStatement createPreparedStatement(Connection con)throws SQLException {PreparedStatement ps = con.prepareStatement(addTeacherSQL,new String[] { "id" });ps.setString(1, student.getName());ps.setInt(2, student.getAge());ps.setString(3, student.getSex());return ps;}};jdbcTemplate.update(preparedStatementCreator, keyHolder);System.out.println("獲取到的插入數(shù)據(jù)庫的ID:" + keyHolder.getKey().longValue());}

    在實際開發(fā)中,我們并不太建議使用表自增鍵,因為這種方式會讓開發(fā)變得更加復(fù)雜且降低程序的移植性,在應(yīng)用層中創(chuàng)建主鍵才是主流的方式,可以使用UUID或者通過一個編碼引擎獲取主鍵值。


    批量更改數(shù)據(jù)

    如果需要一次性插入或者更新多條記錄,當(dāng)然可以簡單的通過多次調(diào)用update()方法完成任務(wù),但是這不是最好的實現(xiàn)方案。 更好的選擇是使用JDBCTemplate批量數(shù)據(jù)更改的方法。一般情況下,后者擁有更好的性能,因為更新的數(shù)據(jù)將被批量發(fā)送到數(shù)據(jù)庫中,它減少了對數(shù)據(jù)庫訪問的次數(shù)。

    我們解讀下下面兩個方法:

    • public int[] batchUpdate(String[] sql)
      多條SQL語句組成一個數(shù)組,注意此處的sql語句不能帶參數(shù),該方法以批量方式執(zhí)行這些SQL語句。Spring在內(nèi)部使用JDBC提供的批量更新API完成操作,如果底層的JDBC Driver不支持批量更新操作,Spring將采用逐條更新的方式模擬批量更新。

    • int[] batchUpdate(String sql,BatchPreparedStatementSetter pss)使用本方法對于同一結(jié)構(gòu)的帶參SQL語句多次進行數(shù)據(jù)更新操作。通過BatchPreparedStatementSetter回調(diào)接口進行批量參數(shù)的綁定工作。

    BatchPreparedStatementSetter定義了兩個方法:

    • int getBatchSize():指定本批次的大小
    • void setValues(PreparedStatement ps,int i):為給定的PreparedStatement設(shè)置參數(shù)
    /*** * * @Title: addBatchArtisan* * @Description: 批量更新* * @param artisanList* * @return: void*/public void addBatchArtisan(final List<Artisan> artisanList) {jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {@Overridepublic void setValues(PreparedStatement ps, int index)throws SQLException {Artisan artisan = artisanList.get(index);ps.setString(1, artisan.getUserName());ps.setString(2, artisan.getPassword());}// 指定該批的記錄數(shù)@Overridepublic int getBatchSize() {return artisanList.size();}});System.out.println("batch insert successfully");}

    需要注意的是BatchPreparedStatementSetter是一次性地批量提交數(shù)據(jù),而不會分批提交,getBatchSize()是整批的大小。所以,如果希望將一個List中的數(shù)據(jù)通過BatchPreparedStatementSetter批量更新到數(shù)據(jù)庫中,getBatchSize()就應(yīng)該設(shè)置為List的大小。

    如果List非常大,希望分多次批量提交,則可分段讀取這個大List并暫存到一個小的List中,再將這個小的List通過BatchPreparedStatemetSetter批量保存到數(shù)據(jù)庫中。


    查詢數(shù)據(jù)

    在Spring JDBC中,僅需要指定SQL查詢語句并定義好如何從結(jié)果集中返回數(shù)據(jù)就可以了。

    使用RowCallbackHandler處理結(jié)果集

    Spring提供了org.springframework.jdbc.core.RowCallbackHandler回調(diào)接口,通過該接口可以定義如何從結(jié)果集中獲取數(shù)據(jù). RowCaIlbackHandler接口很簡單,僅有一 個方法void processRow(ResultSet rs) throws SQLException。
    Spring會遍歷結(jié)果集, 對結(jié)果集中的每一行調(diào)用RowCallbackHandler回調(diào)接口處理數(shù)據(jù)。所以用戶無 須 調(diào)用ResultSet的next()方法,而只需要定義好如何獲取結(jié)果行數(shù)據(jù)的邏輯就可以了。

    我們來看個示例

    package com.xgj.dao.basicOperation.retrieve_select;import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List;import org.springframework.jdbc.core.RowCallbackHandler; import org.springframework.jdbc.core.RowMapper; import org.springframework.stereotype.Repository;import com.xgj.dao.demo.BaseDao;/*** * * @ClassName: ArtisanRDao* * @Description: @Repository 標(biāo)注的DAO* * @author: Mr.Yang* * @date: 2017年9月18日 下午6:14:24*/@Repository public class ArtisanRDao extends BaseDao {private static final String selectArtisanUserSql = "select user_name ,password from artisan_user where user_id = ? ";private static final String selectArtisanUsersSql = "select user_name ,password from artisan_user where user_id between ? and ? ";/*** * * @Title: selectArtisanById* * @Description: 取一條數(shù)據(jù)* * @param artisanId* @return* * @return: Artisan*/public Artisan selectArtisanById(int artisanId) {final Artisan artisan = new Artisan();// (1)將結(jié)果集中的數(shù)據(jù)抽取到artisan對象中jdbcTemplate.query(selectArtisanUserSql, new Object[] { artisanId },new RowCallbackHandler() {@Overridepublic void processRow(ResultSet rs) throws SQLException {artisan.setUserName(rs.getString("user_name"));artisan.setPassword(rs.getString("password"));}});return artisan;} }

    如果需要獲取多條記錄,依舊可以使用RowCallbackHandler完成任務(wù),只需要稍微調(diào)整一下結(jié)果集的處理邏輯就可以了。 代碼如下

    /*** * * @Title: selectArtisansByIds* * @Description: 使用RowCallbackHandler獲取多條記錄* * @param beginId* @param toId* @return* * @return: List<Artisan>*/public List<Artisan> selectArtisansByIds(int beginId, int toId) {final List<Artisan> artisanList = new ArrayList<Artisan>();jdbcTemplate.query(selectArtisanUsersSql,new Object[] { beginId, toId }, new RowCallbackHandler() {@Overridepublic void processRow(ResultSet rs) throws SQLException {Artisan artisan = new Artisan();artisan.setUserName(rs.getString("user_name"));artisan.setPassword(rs.getString("password"));artisanList.add(artisan);}});return artisanList;}

    當(dāng)結(jié)果集中沒有數(shù)據(jù)時,并不會拋出異常。只是此時RowCallbackHandle:回調(diào)接口 中定義的處理邏輯沒有得到調(diào)用罷了。


    使用RowMapper<T>處理結(jié)果集

    Spring還提供了一個和RowCallbackHandler功能類似的RowMapper<T>接口,它也可以使用RowMapper定義結(jié)果集映射邏輯,在結(jié)果集為多行記錄時,該接口更 容易使用。RowMapper<T>也只有一個接口方法:

    T mapRow(ResultSet rs, int rowNum)

    看下示例

    /*** * * @Title: selectArtisansByIdsWithRowMapper* * @Description: 使用RowMapper獲取多行結(jié)果集* * @param beginId* @param toId* @return* * @return: List<Artisan>*/public List<Artisan> selectArtisansByIdsWithRowMapper(int beginId, int toId) {return jdbcTemplate.query(selectArtisanUsersSql, new Object[] {beginId, toId }, new RowMapper<Artisan>() {@Overridepublic Artisan mapRow(ResultSet rs, int rowNum) throws SQLException {Artisan artisan = new Artisan();artisan.setUserName(rs.getString("user_name"));artisan.setPassword(rs.getString("password"));return artisan;}});}

    RowCallbackHandler和RowMapper<T>的比較

    從功能上講,RowCallbackHandler和RowMapper沒有太大的區(qū)別,它們都是用于定義結(jié)果集行的讀取邏輯,將ResultSet中的數(shù)據(jù)映射到對象或者List中 。

    RowCallbackHandler接口實現(xiàn)類可以是有狀態(tài)的,而RowMapper的實現(xiàn)類應(yīng)該是無狀態(tài)的。如果RowCallbackHandler實現(xiàn)類是有狀態(tài)的,用戶就不能在多個地方復(fù)用,只有無狀態(tài)的實例都能在不同的地方復(fù)用。

    比如,Spring有一個RowCallbackHandler的實現(xiàn)類是RowCountCallbackHandler,可以計算結(jié)果集行數(shù):

    RowCountCallbackHandler countCallback = new RowCountCallbackHandler(); jdbcTemplate.query("select * from user", countCallback); int rowCount = countCallback.getRowCount();

    可見RowCountCallbackHandler包含了一個記錄結(jié)果集行數(shù)的狀態(tài),在多線程的環(huán)境中,如果沒有進行特殊的處理,就不能在多個地方復(fù)用countCallback實例。

    Spring也提供了幾個RowMapper實現(xiàn)類,如ColumnMapRowMapper和SingleColumnRowMapper。

    • ColumnMapRowMapper將結(jié)果集中的每一行映射為一個
    • MapSingleColumnRowMapper將結(jié)果集中的某一列映射為一個Object。它們都只是定義了映射邏輯,而沒有保持狀態(tài)。

    我們知道,通過JDBC查詢返回一個ResultSet結(jié)果集時,JDBC并不會一次性將所有匹配的數(shù)據(jù)都加載到JVM中,而是只返回同一批次的數(shù)據(jù)(由JDBC驅(qū)動程序決定,如Oracle的JDBC驅(qū)動程序默認(rèn)返回10行數(shù)據(jù)),當(dāng)通過ResultSet#next()游標(biāo)流動結(jié)果集超過數(shù)據(jù)范圍時,JDBC再獲取一批數(shù)據(jù)。這樣以一種“批量化+串行化”的處理方式避免大結(jié)果集處理時JVM內(nèi)存的過大開銷。

    當(dāng)處理大結(jié)果集數(shù)據(jù)時,如果使用RowMapper,則雖然獲取數(shù)據(jù)的過程是串行化的,但是結(jié)果集中的所有數(shù)據(jù)最終都會映射并匯總成一個List對象,占用大量的JVM內(nèi)存,甚至可以直接引發(fā)OutOfMemoryException異常。這里應(yīng)該使用RowCallbackHandler接口,在processRow接口方法內(nèi)部處理結(jié)果集數(shù)據(jù)。

    當(dāng)使用RowCallbackHandler接口時,如果結(jié)果集中沒有數(shù)據(jù),并不會拋出異常,只是此時RowCallbackHandler回調(diào)接口中定義的處理邏輯沒有得到調(diào)用罷了。


    查詢單值數(shù)據(jù)

    Both queryForInt() and queryForLong() are deprecated since version 3.2.2 . To fix it, replace the code with queryForObject(String, Class).

    package com.xgj.dao.basicOperation.getSingleValue;import org.springframework.stereotype.Repository;import com.xgj.dao.basicOperation.BaseDao;/*** * * @ClassName: GetCountOfArtisanDao* * @Description: @Repository 標(biāo)注的DAO* * @author: Mr.Yang* * @date: 2017年9月19日 下午12:05:08*/@Repository public class GetCountOfArtisanDao extends BaseDao {private final static String COUNTSQL = "select count(1) from artisan_user where user_name = ? ";/*** * * @Title: getCount* * @Description: Both queryForInt() and queryForLong() are deprecated since* version 3.2.2 (correct me if mistake). To fix it, replace* the code with queryForObject(String, Class).* * https://www.mkyong.com/spring/jdbctemplate-queryforint-is-* deprecated/* * @return* * @return: int*/public boolean getCount(String userName) {boolean isExist = false;int count = jdbcTemplate.queryForObject(COUNTSQL,new Object[] { userName }, Integer.class);if (count > 0) {isExist = true;} else {isExist = false;}return isExist;} }

    調(diào)用存儲過程(3種方式)

    CallProcDemo

    package com.xgj.dao.basicOperation.callProc;import java.sql.CallableStatement; import java.sql.SQLException; import java.sql.Types;import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.CallableStatementCallback; import org.springframework.stereotype.Repository;import com.xgj.dao.demo.BaseDao;@Repository public class CallProcDemo extends BaseDao {// (1) 調(diào)用存過的語句private static final String PROCSQL_STRING = "call PROC_artisan_oper(?,?)";public int getUserCount(final String userName) {int num = jdbcTemplate.execute(PROCSQL_STRING,new CallableStatementCallback<Integer>() {@Overridepublic Integer doInCallableStatement(CallableStatement cs)throws SQLException, DataAccessException {// (2)綁定入?yún)?/span>cs.setString(1, userName);// (3)注冊輸出參數(shù)cs.registerOutParameter(2, Types.INTEGER);// 執(zhí)行cs.execute();return cs.getInt(2);}});System.out.println("num:" + num);return num;} }

    CallProcDemoWithSimpleJdbcCall

    package com.xgj.dao.basicOperation.callProc;import java.util.Map;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; import org.springframework.jdbc.core.namedparam.SqlParameterSource; import org.springframework.jdbc.core.simple.SimpleJdbcCall; import org.springframework.stereotype.Repository;@Repository public class CallProcDemoWithSimpleJdbcCall {private JdbcTemplate jdbcTemplate;@Autowiredpublic void setJdbcTemplate(JdbcTemplate jdbcTemplate) {this.jdbcTemplate = jdbcTemplate;}public void getUserCount(int userId) {SimpleJdbcCall jdbcCall = new SimpleJdbcCall(jdbcTemplate).withProcedureName("PROC_artisan_selectInfo_withId");// 如果調(diào)用function 則為withFunctionName(functionName)// 注冊入?yún)?必須和存過的入?yún)⒈3忠恢?不區(qū)分大小寫SqlParameterSource in = new MapSqlParameterSource().addValue("p_user_id", userId);// 獲取返回結(jié)果Map<String, Object> outMap = jdbcCall.execute(in);for (Map.Entry<String, Object> entry : outMap.entrySet()) {System.out.println("key=" + entry.getKey() + ",value="+ entry.getValue());}String userName = (String) outMap.get("O_USERNAME");String password = (String) outMap.get("O_PASSWORD");System.out.println("userName:" + userName + " ,password=" + password);} }

    CallProcDemoWithCallableStatementCreator

    package com.xgj.dao.basicOperation.callProc;import java.sql.CallableStatement; import java.sql.SQLException; import java.sql.Types; import java.util.HashMap; import java.util.Map;import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.CallableStatementCallback; import org.springframework.jdbc.core.CallableStatementCreator; import org.springframework.jdbc.core.CallableStatementCreatorFactory; import org.springframework.jdbc.core.SqlOutParameter; import org.springframework.jdbc.core.SqlParameter; import org.springframework.stereotype.Repository;import com.xgj.dao.demo.BaseDao;@Repository public class CallProcDemoWithCallableStatementCreator extends BaseDao {private static final String PROCSQL_STRING = "call PROC_artisan_selectInfo_withId(?,?,?)";@SuppressWarnings({ "rawtypes", "unchecked" })public void printUserInfo(int userId) {// 使用CallableStatementCreatorFactory 創(chuàng)建 CallableStatementCreatorCallableStatementCreatorFactory factory = new CallableStatementCreatorFactory(PROCSQL_STRING);// 設(shè)置入?yún)actory.addParameter(new SqlParameter("p_user_id", Types.INTEGER));// 設(shè)置出參factory.addParameter(new SqlOutParameter("o_username", Types.VARCHAR));factory.addParameter(new SqlOutParameter("o_password", Types.VARCHAR));Map<String, Integer> paramMap = new HashMap<String, Integer>();paramMap.put("p_user_id", userId);CallableStatementCreator csc = factory.newCallableStatementCreator(paramMap);String userInfo = jdbcTemplate.execute(csc,new CallableStatementCallback() {@Overridepublic Object doInCallableStatement(CallableStatement cs)throws SQLException, DataAccessException {// 執(zhí)行cs.execute();// 獲取返回結(jié)果String userName = cs.getString(2);String password = cs.getString(3);String returnInfo = userName + "|" + password;return returnInfo;}});System.out.println("UserInfo:" + userInfo);} }

    示例源碼

    代碼已托管到Github—> https://github.com/yangshangwei/SpringMaster

    總結(jié)

    以上是生活随笔為你收集整理的Spring JDBC-使用Spring JDBC访问数据库的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。