前些天發現了一個巨牛的人工智能學習網站,通俗易懂,風趣幽默,忍不住分享一下給大家。點擊跳轉到教程。
為了使 JDBC 更加易于使用,Spring 在 JDBCAPI 上定義了一個抽象層, 以此建立一個JDBC存取框架.
作為 SpringJDBC 框架的核心, JDBC 模板的設計目的是為不同類型的JDBC操作提供模板方法. 每個模板方法都能控制整個過程,并允許覆蓋過程中的特定任務.通過這種方式,可以在盡可能保留靈活性的情況下,將數據庫存取的工作量降到最低.
JdbcTemplate主要提供以下五類方法:
execute方法:可以用于執行任何SQL語句,一般用于執行DDL語句;
update方法及batchUpdate方法:update方法用于執行新增、修改、刪除等語句;batchUpdate方法用于執行批處理相關語句;
query方法及queryForXXX方法:用于執行查詢相關語句;
call方法:用于執行存儲過程、函數相關語句。
使用示例:
在數據庫中先準備兩張表:
和
在java工程中創建兩個對應類:
?
- public?class?Department?{??
- ????int?id;??
- ????String?deptName;??
- ????@Override??
- ????public?String?toString()?{??
- ????????return?"Department?[id="?+?id?+?",?deptName="?+?deptName?+?"]";??
- ????}??
- ??????
- }??
- public?class?Employee?{??
- ????int?id;??
- ????String?lastName;??
- ????String?email;??
- ????Department?department;??
- ????@Override??
- ????public?String?toString()?{??
- ????????return?"Employee?[id="?+?id?+?",?lastName="?+?lastName?+?",?email="??
- ????????????????+?email?+?",?department="?+?department?+?"]";??
- ????}??
- ????public?int?getId()?{??
- ????????return?id;??
- ????}??
- ????public?void?setId(int?id)?{??
- ????????this.id?=?id;??
- ????}??
- ????public?String?getLastName()?{??
- ????????return?lastName;??
- ????}??
- ????public?void?setLastName(String?lastName)?{??
- ????????this.lastName?=?lastName;??
- ????}??
- ????public?String?getEmail()?{??
- ????????return?email;??
- ????}??
- ????public?void?setEmail(String?email)?{??
- ????????this.email?=?email;??
- ????}??
- ????public?Department?getDepartment()?{??
- ????????return?department;??
- ????}??
- ????public?void?setDepartment(Department?department)?{??
- ????????this.department?=?department;??
- ????}??
- ??????
- ??????
- }??
?
引入Spring框架相關的jar包以及c3p0和mysql連接jar包。為了對方法進行測試,這里還需要引入JUnit4.這里以導入外部屬性文件的方式來配置數據源:
?
?
jdbc.properties文件內容如下:
?
- user=root??
- password=123??
- driverClass=com.mysql.jdbc.Driver??
- jdbcUrl=jdbc:mysql:///spring??
- ??
- initPoolSize=5??
- maxPoolSize=10??
在xml文件中,導入這個屬性文件以及配置c3p0數據源:
?
?
- <!--?導入資源文件?-->??
- <context:property-placeholder?location="classpath:jdbc.properties"/>??
- ??
- <!--?配置?c3p0?數據源?-->??
- <bean?id="dataSource"??
- ????class="com.mchange.v2.c3p0.ComboPooledDataSource">??
- ????<property?name="user"?value="${user}"></property>?????
- ????<property?name="password"?value="${password}"></property>?????
- ????<property?name="jdbcUrl"?value="${jdbcUrl}"></property>???
- ????<property?name="driverClass"?value="${driverClass}"></property>???
- ??????
- ????<property?name="initialPoolSize"?value="${initPoolSize}"></property>??????
- ????<property?name="maxPoolSize"?value="${maxPoolSize}"></property>???
- </bean>??
配置好dataSource后就可以用這個數據源來配置JdbcTemplate了,在xml文件中添加:
?
?
- <!--?配置?spring?的?JdbcTemplate?-->??
- <bean?id="jdbcTemplate"??
- ????class="org.springframework.jdbc.core.JdbcTemplate">??
- ????<property?name="dataSource"?ref="dataSource"></property>??
- </bean>??
接下來創建一個測試類對JdbcTemplate的方法進行測試:
?
?
- import?java.util.ArrayList;??
- import?java.util.List;??
- ??
- import?org.junit.Test;??
- import?org.springframework.context.ApplicationContext;??
- import?org.springframework.context.support.ClassPathXmlApplicationContext;??
- import?org.springframework.jdbc.core.BeanPropertyRowMapper;??
- import?org.springframework.jdbc.core.JdbcTemplate;??
- import?org.springframework.jdbc.core.RowMapper;??
- ??
- public?class?JDBCTest?{??
- ??????
- ????private?ApplicationContext?ctx=?null;??
- ????private?JdbcTemplate?jdbcTemplate?=?null;??
- //??private?EmployeeDao?employee;??
- ??
- ????{??
- ????????ctx?=?new?ClassPathXmlApplicationContext("ApplicationContext.xml");??
- ????????jdbcTemplate?=?(JdbcTemplate)?ctx.getBean("jdbcTemplate");??
- ????}??
- ??
- ????/**?
- ?????*?執行?INSERT,UPDATE,DELETE?
- ?????*/??
- ????@Test??
- ????public?void?testUpdate()?{??
- ????????String?sql?=?"UPDATE?employees?SET?last_name?=???WHERE?id?=??";??
- ????????jdbcTemplate.update(sql,?"Jack",?5);??
- ????}??
- ????/**?
- ?????*?測試批量更新操作?
- ?????*?最后一個參數是?Object[]?的?List?類型:因為修改一條記錄需要一個?Object?數組,修改多條記錄就需要一個?List?來存放多個數組。?
- ?????*/??
- ????@Test??
- ????public?void?testBatchUpdate()?{??
- ????????String?sql?=?"INSERT?INTO?employees(last_name,?email,?dept_id)?VALUES(?,?,?)";??
- ??????????
- ????????List<Object[]>?batchArgs?=?new?ArrayList<>();??
- ??????????
- ????????batchArgs.add(new?Object[]{"AA",?"aa@atguigu.com",?1});??
- ????????batchArgs.add(new?Object[]{"BB",?"bb@atguigu.com",?2});??
- ????????batchArgs.add(new?Object[]{"CC",?"cc@atguigu.com",?3});??
- ????????batchArgs.add(new?Object[]{"DD",?"dd@atguigu.com",?3});??
- ????????batchArgs.add(new?Object[]{"EE",?"ee@atguigu.com",?2});??
- ??????????
- ????????jdbcTemplate.batchUpdate(sql,?batchArgs);??
- ????}??
- ??????
- ????/**?
- ?????*?從數據庫中獲取一條記錄,實際得到對應的一個對象?
- ?????*?注意:不是調用?queryForObject(String?sql,?Class<Employee>?requiredType,?Object...?args)?方法!?
- ?????*?而需要調用?queryForObject(String?sql,?RowMapper<Employee>?rowMapper,?Object...?args)?
- ?????*?1、其中的?RowMapper?指定如何去映射結果集的行,常用的實現類為?BeanPropertyRowMapper?
- ?????*?2、使用?SQL中的列的別名完成列名和類的屬性名的映射,例如?last_name?lastName?
- ?????*?3、不支持級聯屬性。?JdbcTemplate?只能作為一個?JDBC?的小工具,?而不是?ORM?框架?
- ?????*/??
- ????@Test??
- ????public?void?testQueryForObject()?{??
- ????????String?sql?=?"SELECT?id,?last_name?lastName,email,dept_id?as?\"department.id\"?FROM?employees?WHERE?ID?=??";??
- ????????RowMapper<Employee>?rowMapper?=?new?BeanPropertyRowMapper<>(Employee.class);??
- ????????//在將數據裝入對象時需要調用set方法。??
- ????????Employee?employee?=?jdbcTemplate.queryForObject(sql,?rowMapper,?1);??
- ??????????
- ????????System.out.println(employee);??
- ????}??
- ??????
- ????/**?
- ?????*?一次查詢多個對象?
- ?????*?注意:調用的不是?queryForList?方法?
- ?????*/??
- ????@Test??
- ????public?void?testQueryForList()?{??
- ????????String?sql?=?"SELECT?id,?last_name?lastName,?email?FROM?employees?WHERE?id?>??";??
- ????????RowMapper<Employee>?rowMapper?=?new?BeanPropertyRowMapper<>(Employee.class);??
- ????????List<Employee>?employees?=?jdbcTemplate.query(sql,?rowMapper,5);??
- ??????????
- ????????System.out.println(employees);??
- ????}??
- ????/**?
- ?????*?獲取單個列的值或做統計查詢?
- ?????*?使用?queryForObject(String?sql,?Class<Long>?requiredType)??
- ?????*/??
- ????@Test??
- ????public?void?testQueryForObject2()?{??
- ????????String?sql?=?"SELECT?count(id)?FROM?employees";??
- ????????long?count?=?jdbcTemplate.queryForObject(sql,?Long.class);??
- ??????????
- ????????System.out.println(count);??
- ????}?????
- }??
在實際的使用中,一般會創建一個dao類來封裝對某個對象的所有增刪改查操作.
?
比如,創建一個EmployeeDao類如下:
?
- import?org.springframework.beans.factory.annotation.Autowired;??
- import?org.springframework.jdbc.core.BeanPropertyRowMapper;??
- import?org.springframework.jdbc.core.JdbcTemplate;??
- import?org.springframework.jdbc.core.RowMapper;??
- import?org.springframework.stereotype.Repository;??
- ??
- @Repository??
- public?class?EmployeeDao?{??
- ????@Autowired??
- ????private?JdbcTemplate?jdbcTemplate;??
- ??????
- ????public?Employee?get(Integer?id)?{??
- ????????String?sql?=?"SELECT?id,?last_name?lastName,?email?FROM?employees?WHERE?id?=??";??
- ????????RowMapper<Employee>?rowMapper?=?new?BeanPropertyRowMapper<>(Employee.class);??
- ????????Employee?employee?=?jdbcTemplate.queryForObject(sql,?rowMapper,?id);??
- ??????????
- ????????return?employee;??
- ????}??
- }??
在這個Dao類中實現了通過id來獲取記錄并封裝成對象返回的方法。如果有需要還可以實現其他操作如插入、刪除、更新等。
?
由于這里使用了注解來配置bean以及bean的自動裝配,所以還需要在xml文件中添加(要先導入context命名空間):
?
- <context:component-scan?base-package="com.atguigu.spring.jdbc"></context:component-scan>??
測試一下EmployeeDao:
?
?
- @Test??
- public?void?testEmployeeDao()?{??
- ????EmployeeDao?employeeDao?=?(EmployeeDao)?ctx.getBean("employeeDao");??
- ????Employee?employee?=?employeeDao.get(1);??
- ????System.out.println(employee);??
- }??
打印輸出如下:
?
總結:JdbcTemplate是Spring框架自帶的對JDBC操作的封裝,目的是提供統一的模板方法使對數據庫的操作更加方便、友好,效率也不錯。但是功能還是不夠強大(比如不支持級聯屬性),在實際應用中還需要和hibernate、mybaties等框架混合使用。
?