肝!Spring JDBC持久化層框架「全家桶」教程

目錄

一、什麼是JdbcTemplate?

二、JdbcTemplate框架搭建

(1)、直接在中配置數據源

(2)、引入外部配置文件

3、配置JdbcTemplate對象

四、使用具名參數的JdbcTemplate

3、通過SqlParameterSource對象傳入數值

五、自動裝配JdbcTemplate並實現Dao

寫在前面

Hello,你好呀,我是 灰小猿 ,一個超會寫bug的程序猿!

**用堅持締造技術、用指尖敲動未來!** 願我們每一次敲動鍵盤,都能讓生活變得更智能、世界變得更有趣!

在使用Spring進行業務邏輯層處理時,你是否有想過,如此強大的Spring框架在對數據庫相關的業務處理時,是否有更加便捷的操作呢?Spring框架又能將傳統JDBC數據庫的操作優化到什麼樣的程度呢?

今天我就來和大家一起探究一下針對JDBC數據庫操作的一個輕量級框架— JdbcTemplate 。教你一篇文掌握Spring JDBC框架的核心。

一、什麼是JdbcTemplate?

Spring的JdbcTemplate可以被看作是一個小型的輕量級持久化層框架,為了使JDBC操作更加便捷,Spring在JDBC API上定義了一個抽象層,以此來建立了一個JDBC存取框架。

它作為Spring JDBC框架的核心, 設計目的是為不同類型的JDBC操作提供模版方法,以至於通過這種方式,在儘可能保留靈活性的前提下,將數據庫存取的工作量降低到最低。

現在對於什麼是jdbcTemplate你應該比較了解了吧?那麼接下來我就來和大家詳細的聊一聊這個輕量級的框架是如何使用的。

二、JdbcTemplate框架搭建

使用JdbcTemplate進行數據庫的相關操作是需要提前搭建好相關環境配置的。那麼我們就先來講一下如何在spring中配置JdbcTemplate。

1、導入所需jar包

我們知道平常在進行框架的搭建的時候都是需要依賴相關的Jar包來實現的。那麼JdbcTemplate又需要哪些jar包呢?我給大家按照作用羅列並整理了出來,

①IOC容器所需要的JAR包

  • commons-logging-1.1.1.jar
  • spring-beans-4.0.0.RELEASE.jar
  • spring-context-4.0.0.RELEASE.jar
  • spring-core-4.0.0.RELEASE.jar
  • spring-expression-4.0.0.RELEASE.jar

②JdbcTemplate所需要的JAR包

  • spring-jdbc-4.0.0.RELEASE.jar
  • spring-orm-4.0.0.RELEASE.jar
  • spring-tx-4.0.0.RELEASE.jar

③數據庫驅動和數據源

  • c3p0-0.9.1.2.jar
  • mysql-connector-java-5.1.7-bin.jar

以上這些jar包,包括SSM開發所需的所有jar包我給大家整理了出來,下載就能使用。

SSM框架Jar包下載

現在導入了所有所依賴的jar包,接下來就是利用這些資源搭建接下來的JdbcTemplate框架了,

2、配置JDBC數據源

既然是對數據庫的操作,那麼就一定是需要數據源的,我們以MySQL數據庫為例進行數據源的配置操作,關於在IOC中對bean的賦值我之前也和大家講過,所以我們可以直接在IOC容器中配置出數據源,連接到指定的數據庫,這裡需要藉助 CombopooledDataSource 類,並在其中給user、password、jdbcurl、driverclass等這幾個屬性賦值。同時我們配置上連接池中的最大連接數量和最小連接數量(當然這兩個屬性也是可以不用配置的)。

在這裡配置數據源對屬性的賦值其實也有兩種方式:

一種是直接將連接信息在標籤中寫死。

第二種是將數據源的連接信息寫在單獨的一個文件中,然後引入外部配置文件,這裡我將兩種方法都介紹給大家:

(1)、直接在中配置數據源

使用這種方法只需要直接在value中將屬性的值寫死就可以了,同時寫入數據源的id,代碼如下:

<Bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <property name="user" value="root"/>
    <property name="password" value="admin"/>
    <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/jdbc_template"/>
    <property name="driverClass" value="com.mysql.jdbc.Driver"/>
    <property name="minPoolSize" value="5"/>
    <property name="maxPoolSize" value="20"/>
</bean>
複製代碼

(2)、引入外部配置文件

第二種方式是引入外部帶有數據源連接信息的配置文件,然後利用引入外部配置文件的標籤將數據源信息引入進來,再利用**${}表達式**將數據值賦值給屬性, 使用這種方法的好處就是在數據源變更的時候方便更改變更信息,直接在數據源的文件中更新即可,不需要在IOC容器中更改代碼。

這種方法需要我們首先建立數據源信息的配置文件,如jdbcconfig.properties,當然你還可以定義成其他名字,如「xxx.properties」。**但是一般都要以「.properties」為文件後綴。**文件中寫入數據源信息:

jdbc.user=root
jdbc.password=ADMIN
jdbc.jdbcurl=jdbc:mysql://localhost:3306/jdbc_template
jdbc.driverClass=com.mysql.jdbc.Driver
複製代碼

在IOC容器中使用標籤context:property-placeholder引入外部配置文件「jdbcconfig.properties」。

<!-- 添加外部配置文件 -->
<context:property-placeholder location="classpath:jdbcconfig.properties"/>
複製代碼

**注意:** 這裡的class表示類路徑下的文件。

之後按照同樣的方式在容器中標籤下配置數據源,但是現在賦值是使用「 ${} 」獲取到的jdbcconfig.properties中的配置數據。代碼如下:

<!-- 設置數據庫配置
在這裡要注意:
$是用於讀取配置文件中的信息
#是用於spring應用
-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <property name="user" value="${jdbc.user}"></property>
    <property name="password" value="${jdbc.password}"></property>
    <property name="jdbcUrl" value="${jdbc.jdbcurl}"></property>
    <property name="driverClass" value="${jdbc.driverClass}"></property>
</bean>
複製代碼

3、配置JdbcTemplate對象

在我們配置好數據源之後,就是配置JdbcTemplate對象了, 由於JdbcTemplate對象只是一個JDBC的操作模版,因此它需要引入外部要操作的數據源。具體操作是在IOC中為JdbcTemplate類的dataSource屬性賦予數據源。

代碼如下:

<!-- 建立一個jdbcTemplate連接 -->
<bean id="jdbcTemplate"  class="org.springframework.jdbc.core.JdbcTemplate">
	<constructor-arg name="dataSource" ref="dataSource"></constructor-arg>
</bean>
複製代碼

直到這裡,JdbcTemplate這個「輕量級」框架才算搭建配置完成了,接下來就能正常使用JdbcTemplate進行數據庫中的相關操作了,我們先來寫一個測試語句分別測試一下在普通連接和使用JdbcTemplate連接的情況下,數據庫連接是否正常:

public class JdbcTest {

	ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
	JdbcTemplate jdbcTemplate = context.getBean(JdbcTemplate.class);
		
//	通過普通方法來獲取數據庫連接
	@Test
	public void test() throws SQLException {
		System.out.println("jdbc_template執行");
		DataSource bean = context.getBean(DataSource.class);
		Connection connection = bean.getConnection();
		System.out.println("普通方法來獲取數據庫連接:" + connection);
		
	}
	         
	/**
	 * 通過jdbcTemplate來獲取數據庫連接
	 * 實驗:測試數據源
	 * */
	@Test
	public void test01() {
		System.out.println("jdbcTemplate來獲取數據庫連接:" + jdbcTemplate);
	}

}
複製代碼

運行出現如下信息,表示連接正常:

確認數據庫連接正常之後,現在才是到了JdbcTemplate使用的核心部分,敲黑板!到重點咯!!!

三、持久化層操作詳解

JdbcTemplate有專門的操作函數來實現不同的增刪改查操作,接下來我將通過如下數據表「員工表employee」來給大家介紹一下他們的具體使用:

1、增刪改操作

非常神奇的是,JdbcTemplate的增刪改操作是使用同一個方法來完成的,即:

JdbcTemplate.update(String, Object...)

該方法最常用的有兩個參數:

第一個參數String傳入需要執行的SQL語句,

第二個參數Object...傳入sql語句中需要帶的參數,使用object...的意思就是後面可能不止一個參數。該方法會有一個int類型的返回值,表示有多少行數據被修改了,下面我通過一個實例來給大家演示一下;

例:將emp_id=5的記錄的salary字段更新為1300.00

首先我們需要寫出相應的sql語句,語句中需要傳入參數的位置使用「?」表示,之後調用update方法來實現修改操作,並返回被修改的行數:

/** 修改數據庫的數據表中的數據
 * 將emp_id=5的記錄的salary字段更新為1300.00*/
// @Test
public void test02() {
    String sql = "UPDATE employee SET salary=? WHERE emp_id=?";
    int update = jdbcTemplate.update(sql, 1300.00, 5);
    System.out.println("更新成功!" + update);
}
複製代碼

以上是一個修改操作,對於刪除和添加操作使用同樣的方式即可。

2、批量增刪改操作

上面是對於普通的單條數據的增刪改操作,但是如果有大量的數據需要執行同一個操作呢?一個一個的來豈不是太麻煩了嘛?所以針對這一情況JdbcTemplate還特意提供了批量的增刪改方法,方便我們對大量數據的操作。具體使用是這樣的。

通過調用以下函數來實現:

JdbcTemplate.batchUpdate(String, List<Object[]>)

該方法會返回一個int類型的數組,數組中存放着每次執行sql語句所修改的行數。

其中的String仍然表示要執行的sql語句,

但是Object[]封裝了SQL語句每一次執行時所需要的參數,而在List集合封裝了SQL語句多次執行時的所有參數。

我們通過下面這個實例來驗證這一方法的操作:

例:向employee表中批量插入數據

首先需要將sql語句寫好,然後將需要傳遞的參數寫入到list集合中,之後再將sql語句和list集合傳入batchUpdate()方法即可。

/**
	 * 批量插入數據
	 * */
	@Test
	public void test03() {
		String sql = "INSERT INTO employee(emp_name,salary) VALUES(?,?)";
		List<Object[]> batchArgs = new ArrayList<Object[]>();
		batchArgs.add(new Object[]{"張三","999"});
		batchArgs.add(new Object[]{"李四","1999"});
		batchArgs.add(new Object[]{"王五","2999"});		
		int[] batchUpdate = jdbcTemplate.batchUpdate(sql, batchArgs);
		for (int i : batchUpdate) {
			System.out.println(i);
		}
	}
	
複製代碼

3、查詢單行數據

上面我們了解了在jdbcTemplate中如何進行增刪改操作,那麼CRUD四兄弟怎麼能少看查找這麼重要的操作呢?這不它來了!!!

在jdbcTemplate中查詢數據其實是十分簡單的,但是他為什麼不與其他三個操作共同使用同一個操作方法呢?

**原因其實很簡單,**還不就是增刪改操作會對數據表進行修改而返回int型的修改行數,而查詢操作不會對數據表修改,同時返回其他類型的查詢結果!

首先我們來看一下如何查詢單行數據。在jdbcTemplate中查詢單行數據所使用的函數是:

JdbcTemplate.queryForObject(String, RowMapper, Object...)

該方法的參數中String同樣的表示要執行查找的sql語句,

**但是這裡有一個坑要注意:**中間傳遞的參數 RowMapper這個是什麼呢?其實這裡值的是要傳遞需要返回的bean對象的類型,**但是在進行真正的使用的時候我們並不是通過RowMapper來映射要返回的bean對象的,而是通過它的子類Bea****nPropertyRowMapper,**他們的繼承關心是這樣的:

在使用BeanPropertyRowMapper映射所返回的bean對象時,能夠找到該對象並映射成功則返回,如果找不到就報錯。

第三個參數object...還是表示傳入的查詢參數。

下面看這樣一個實例你就明白了。

例:查詢emp_id=5的數據庫記錄,封裝為一個Java對象返回。

/**
	 * 查詢數據庫中的單條數據
	 * 實驗4:查詢emp_id=5的數據庫記錄,封裝為一個Java對象返回
	 * 創建的javabean中的字段要和數據表中的字段名一樣,否則就需要進行映射
	 * 查詢單條數據使用 queryForObject,但是中間需要使用BeanPropertyRowMapper映射需要生成的bean對象
	 * 		在查找不到的時候會報錯
	 * 
	 * */
	@Test
	public void test04() {
		String sql = "SELECT * FROM employee WHERE emp_id=?";
		Employee employee = null;
		try {
			employee = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<Employee>(Employee.class),5);
		} catch (Exception e) {
			// TODO: handle exception
		}
		System.out.println(employee);
		
	}
複製代碼

4、查詢多行數據

與查詢單行數據不同,查詢多行數據需要使用的方法是:

JdbcTemplate.query(String, RowMapper, Object...)

但是其中所傳遞的參數是一樣的, 唯一不同是該方法返回的是一個數組列表,其中包含了查詢到的每一條數據。

如下面這個實例:

例:查詢salary>4000的數據庫記錄,封裝為List集合返回。

/**
	 * 查詢數據庫中的多條數據
	 * 實驗5:查詢salary>4000的數據庫記錄,封裝為List集合返回
	 * */
	@Test
	public void test05() {
		String sql  = "SELECT * FROM employee WHERE salary>?";
		List<Employee> employees = jdbcTemplate.query(sql, new BeanPropertyRowMapper<Employee>(Employee.class),4000);
		for (Employee employee : employees) {
			System.out.println(employee);
		}
	}
複製代碼

5、查詢單一指定數值

現在我們知道了如何查詢單條數據,也知道了如何查詢多條數據,但是這些數據返回的都是成行的數據,假如說我們只想得到某一行的數據呢?

那也好辦。jdbcTemplate有一個專門的方法用來返回需要查詢單一數值。

JdbcTemplate.queryForObject(String, Class, Object...)

該方法中有一個返回值是class,它表示要返回的數據的類型,比如是int類型還是double類型。同時方法返回查詢到的該數值。

如下面這裡實例:

例:查詢employee表中最大的salary。

該方法很顯然是返回一個具體的數值,而且還是沒有參數的,那麼我們在進行參數的傳遞的時候就不需要傳遞後面的object...類型參數。

/**
	 * 查詢數據表中的數據,但是只返回一個數值
	 * 實驗6:查詢最大salary
	 * */
	@Test
	public void test06() {
		String sql = "SELECT MAX(salary) FROM employee";
		Double quDouble = jdbcTemplate.queryForObject(sql, Double.class);
		System.out.println(quDouble);
	}
複製代碼

以上就是使用jdbcTemplate實現不同增刪改查操作的全部方法了,但是操作jdbcTemplate還有一種方式,就是將sql語句中的「?」用具體的參數來表示。接下來我們來介紹一下這種方式執行sql語句。

四、使用具名參數的JdbcTemplate

接下來要介紹的這個JdbcTemplate的操作方式與上面的有一點不太一樣,這裡使用了一個具名參數來表示sql語句中需要傳入的參數,那麼什麼是具名參數呢?

**具名參數:**指具有名字的參數,參數不再是佔位符,而是一個變量名

語法格式:「:參數名」

使用該具名參數之後,spring會自動的從傳入的參數中查找具有相應名稱的參數,並將它的值賦值給sql語句。

而Spring有一個支持具名參數功能的jdbcTemplate,即NamedParameterJdbcTemplate類,在在Spring中可以通過NamedParameterJdbcTemplate類的對象使用帶有具名參數的SQL語句。

1、聲明具名參數類

使用NamedParameterJdbcTemplate類的方式與普通的JdbcTemplate類似,都需要在ioc中聲明,如下所示:

<!-- 建立一個帶有具名參數支持的jdbcTemplate -->
<bean id="namedParameterJdbcTemplate" class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
    <constructor-arg name="dataSource" ref="dataSource"></constructor-arg>
</bean>
複製代碼

2、具名參數的普通使用

我們以插入語句為例,來演示一下具名參數的使用,

傳統的sql語句是這樣的:

INSERT INTO employee(emp_name,salary) values(?,?)
複製代碼

使用具名參數的sql語句是這樣的;

INSERT INTO employee(emp_name,salary) values(:emp_name,:salary)
複製代碼

如下面這個實例:

例:使用帶有具名參數的SQL語句插入一條員工記錄,並以Map形式傳入參數值。

/**
	 * 實驗7:使用帶有具名參數的SQL語句插入一條員工記錄,並以Map形式傳入參數值
	 * 佔位符查參數:?的順序千萬不能錯,傳參的時候一定要注意
	 * */
	@Test
	public void test07() {
		String sql = "INSERT INTO employee(emp_name,salary) values(:emp_name,:salary)";
		Map<String, Object> paramMap = new HashMap<String, Object>();
		paramMap.put("emp_name", "趙六");
		paramMap.put("salary", 998.12);
		int updateNum = jdbcTemplate2.update(sql, paramMap);
		System.out.println(updateNum);
	}
複製代碼

**這裡有一點需要注意的是:**無論是使用普通的sql語句、還是使用帶具名參數的sql語句。傳入的參數的順序都需要和sql語句中參數的順序一致,否則就會出現參數調用錯誤,這一點一定需要注意!

3、通過SqlParameterSource對象傳入數值

通過SqlParameterSource對象傳入數值其實也就是需要將參數以javabean的形式傳入,但是又有了需要注意的地方。

注意:在使用sqlParmeterSource進行數據庫中數據裝填的時候,一定要注意values後面的參數名稱和bean中的參數名稱對應

否則就會報如下錯誤:

No value supplied for the SQL parameter 'emp_Name': Invalid property 'emp_Name' of bean class [com.spring.beans.Employee]: Bean property 'emp_Name' is not readable or has an invalid getter method:

下面以一個實例來說明通過SqlParameterSource對象傳入參數。

例:使用帶有具名參數的SQL語句插入一條員工記錄,通過SqlParameterSource對象傳入參數。

/**
 * 實驗8:重複實驗7,以SqlParameterSource形式傳入參數值
 * */
	@Test
	public void test08() {
		String sql = "INSERT INTO employee(emp_name,salary) values(:emp_name,:salary)";
		Employee employee = new Employee();
		employee.setEmp_name("吳九");
		employee.setSalary(997.7);
		int updateNum = jdbcTemplate2.update(sql, new BeanPropertySqlParameterSource(employee));
		System.out.println(updateNum);
	}
複製代碼

五、自動裝配JdbcTemplate並實現Dao

**由於JdbcTemplate類是線程安全的,**所以可以在IOC容器中聲明它的單個實例,並將這個實例注入到所有的Dao實例中,在Dao類中將JdbcTemplate實現自動裝配。並在其中實現增刪改查方法,通過自動裝配的jdbcTemplate可以在Dao中減少代碼的操作,更加輕鬆的實現增刪改查操作。

通過該方法自動裝配JdbcTemplate並實現Dao的步驟我給大家總結了出來:

  1. 建立dao類
  2. 書寫其中的方法
  3. 利用包掃描將其自動裝配
  4. 從IOC容器中獲取dao類
  5. 實現其中響應的數據庫操作的方法

下面通過實例進行驗證。

例:創建BookDao,自動裝配JdbcTemplate對象,並實現一個添加添加操作。

在Dao類中,我們使用@Autowired註解自動裝配jdbcTemplate,並實現一個數據添加的方法:

@Repository
public class EmployeeDao {
	//	將jdbcTemplate自動注入
	@Autowired
	JdbcTemplate jdbcTemplate;
	/**
	 * 保存數據到數據表
	 * */
	public int saveEmployee(Employee employee) {
		String sql = "insert into employee(emp_name,salary) values(?,?)";
		return jdbcTemplate.update(sql, employee.getEmp_name(),employee.getSalary());
	}	
}
複製代碼

使用測試方法進行測試:

/**
	 * 實驗9:創建BookDao,自動裝配JdbcTemplate對象
	 * */
	@Test
	public void test09() {
		Employee employee = new Employee();
		employee.setEmp_name("王八");
		employee.setSalary(888.7);
		int saveEmployeeNum = employeeDao.saveEmployee(employee);
		System.out.println(saveEmployeeNum);
	}
複製代碼

這樣通過自動裝配JdbcTemplate並實現Dao的工作就完成了,這種方式避免了重複的創建jdbcTemplate,而且減少了代碼量。

六、寫在最後

叮叮!到這裡,Spring的JdbcTemplate框架全部的操作使用就跟大家講解完畢了,

其中包括從普通的JdbcTemplate搭建,到實現簡單的CURD、再到複雜的具名參數。希望小夥伴們通過這一篇文章就能掌握JdbcTemplate的使用教程。同時在學習過程中有遇到不理解或者不會的地方,歡迎留言提出,我們一起學習!

再先進的技術都需要一鍵一鍵的敲出來,奮鬥吧!致奔波在Java道路上的每一位「創造者」!

我是灰小猿,我們下期見!