今天主要學習JdbcTemplate,DBUtils
思維導圖:
一.JdbcTemplate
1.概念:
JdbcTemplate是spring框架對JDBC進行簡便操作所提供一個模板類嗎,這個類core包下面進行提供的JdbcTemplate可以在JDBC的基礎進行一些簡單的CRUD(增刪改查)操作,同時還大量的使用了預編譯操作,所以在性能和安全上都可以達到一個非常優秀的地步。
2. 如何去使用JdbcTemplate:
(1)需要導入jar包(因爲這是一個第三方工具)
所提供的JdbcTemplate目錄下的lib下面的所有包(5個)
(2)創建JdbcTemplate對象
JdbcTemplate template = new JdbcTemplate(JdbcUtils.getDataSource());
注意:這裏的構造方法需要一個DataSource()的具體對象(其實要的就是連接池,因爲JdbcTemplate不具備連接功能,所以需要連接池來驅動它)
(3)調用我們的 JdbcTemplate的各種方法實現對DML和DQL的操作
int update(String sql):適用於沒有修改條件的增刪改(不存在預參數參與)
delete from account;
int update(String sql,Object...):適用於帶有操作條件的增刪改(存在預編譯參數)
delete from account where id = ?;
注意:這個Object...是一個可變參數
3.查詢的結果有哪些?
(1)返回的結果只有單行(查詢之後只能存在一條結果的操作)
Map<String, Object> queryForMap(String var1):適用於沒有預編譯參數的sql
Map<String, Object> queryForMap(String var1, Object... var2):適合存在預編譯參數的sql
注意:
queryForMap只適用於一條結果的查詢,如果是是多條結果則會產生異常,查詢後的結果列會存儲到一個Map集合當中,其中Map的鍵用於存儲列名,Map值則存儲列的數據
(2)返回的結果是全部或者多行(查詢全表數據或者查詢結果存在多條)
List<Map<String, Object>> queryForList(String var1):適用於沒有預編譯參數的sql
List<Map<String, Object>> queryForList(String var1,Object... var2):適合存在預編譯參數的sql
注意:queryForMap適用於多條結果的查詢,如果確保是一條結果則不建議使用它,因爲操作比較複雜其查詢的每一行數據會先存在Map集合當中,然後在將Map集合存儲在List集合噹噹中在正常的開發邏輯當中,我們的每一個數據應該是一個對象的屬性,所有的操作應該以對象作爲中心JdbcTemplate爲了更加的符合面向對象思想,也給我們提供了一個將查詢結果封裝到對象的方法
方式一:手寫轉換處理
List<T> query(String var1, RowMapper<T> var2):
var1:需要操作的SQL
var2:這是一個接口,裏面需要依賴重寫後的mapRow方法,因爲所有查詢的結果全部存在這個方法的ResultSet當中。
方式二:自動轉換處理
template.query(sql,new BeanPropertyRowMapper<UserVO>(UserVO.class));
(3)返回的結果是一個數據(聚合函數的SUM/AVG/COUNT)
queryForObject(String sql, Class<T> requiredType);
sql:需要查詢的SQL語句
requiredType:返回結果和接收結果的數據類型,通過反射加載 一般只能是Double.class和Long.class
例子:
package com.jdbctemlate;
import com.util.JdbcUtils;
import com.vo.UserVO;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class Demo01 {
public static void main(String[] args) {
select05();
}
//一個結果的查詢
public static void select05() {
JdbcTemplate template = new JdbcTemplate(JdbcUtils.getDataSource());
String sql = "select count(id) from ask_users";
Long l = template.queryForObject(sql,Long.class);
System.out.println(l);
}
//自動將查詢結果轉化爲JavaBean
public static void select04() {
JdbcTemplate template = new JdbcTemplate(JdbcUtils.getDataSource());
String sql = "select * from ask_users";
List<UserVO> list = template.query(sql,new BeanPropertyRowMapper<UserVO>(UserVO.class));
for (UserVO userVO : list) {
System.out.println(userVO.getUsername());
System.out.println(userVO.getPassword());
System.out.println(userVO.getEmail());
System.out.println(userVO.getStatus());
System.out.println(userVO.getJob());
System.out.println(userVO.getGender());
System.out.println("--------------------");
}
}
//手動將查詢結果轉化爲JavaBean
public static void select03() {
JdbcTemplate template = new JdbcTemplate(JdbcUtils.getDataSource());
String sql = "select * from ask_users";
//通過子類實現RowMapper,並mapRow方法
//List<UserVO> u = template.query(sql,new MyRowMapper());
//直接使用匿名內部類
// List<UserVO> u = template.query(sql, new RowMapper<UserVO>() {
// @Override
// public UserVO mapRow(ResultSet rs, int i) throws SQLException {
// //創建一個實體對象
// UserVO user = new UserVO();
// user.setUsername(rs.getString("username"));
// user.setEmail(rs.getString("email"));
// user.setGender(rs.getString("gender"));
// user.setId(rs.getInt("id"));
// user.setJob(rs.getString("job"));
// user.setStatus(rs.getInt("Status"));
// return user;
//
// }
// });
//使用Lambda表達式處理
List<UserVO> u1 = template.query(sql,(rs, i) -> {
//創建一個實體對象
UserVO user = new UserVO();
user.setUsername(rs.getString("username"));
user.setEmail(rs.getString("email"));
user.setGender(rs.getString("gender"));
user.setId(rs.getInt("id"));
user.setJob(rs.getString("job"));
user.setStatus(rs.getInt("Status"));
return user;
});
for (UserVO userVO : u1) {
System.out.println(userVO.getUsername());
System.out.println(userVO.getPassword());
System.out.println(userVO.getEmail());
System.out.println(userVO.getStatus());
System.out.println(userVO.getJob());
System.out.println(userVO.getGender());
System.out.println("--------------------");
}
}
//查詢多條結果
public static void select02() {
JdbcTemplate template = new JdbcTemplate(JdbcUtils.getDataSource());
String sql = "select * from ask_users";
List<Map<String, Object>> list = template.queryForList(sql);
/*
* +--------------------------+
* | id | username | password |
* +--------------------------+
* | 1 | admin | root |
* +--------------------------+
* | 2 | toobug | admin |
* +--------------------------+
* ....
*
* 1.將每一條結果轉換成了Map:
* {id = 1,username = admin,password = root}
* {id = 2,username = toobug,password = admin}
* ...
* 2.將Map繼續存儲到List集合當中
* [{id = 1,username = admin,password = root},{id = 2,username = toobug,password = admin}.....]
* */
// System.out.println(list);
//取出結果
//1.先取出每一行的數據(每一個map)
for (Map<String, Object> maps : list) {
//System.out.println(maps);
//2.在map當中取出每一個數據值
for (Map.Entry<String, Object> e : maps.entrySet()) {
System.out.println("列名:" + e.getKey() + "," + "值:" + e.getValue());
}
System.out.println("-------------------------");
}
}
//查詢單條結果
public static void select01() {
JdbcTemplate template = new JdbcTemplate(JdbcUtils.getDataSource());
//查詢ID爲1的用戶數據
String sql = "select * from ask_users where id = ? ";
//String sql = "select * from ask_users where id = ? or name = ?";//錯誤,不能反回多條結果的查詢
Map<String, Object> map = template.queryForMap(sql, 1);
/*
* +--------------------------+
* | id | username | password |
* +--------------------------+
* | 1 | admin | root |
* +--------------------------+
* 轉換成了Map:
* {id = 1,username = admin,password = root}
* */
System.out.println(map);
//判斷賬號是否存在
if (map.get("username").equals("李神仙")) {
System.out.println("賬號已經存在");
} else {
System.out.println("賬號不存在");
}
//對map集合遍歷,取出所有數據
for (Map.Entry<String, Object> e : map.entrySet()) {
System.out.println("列名:" + e.getKey() + "," + "值:" + e.getValue());
System.out.println("-------------------------");
}
}
//修改數據
public static void update() {
JdbcTemplate template = new JdbcTemplate(JdbcUtils.getDataSource());
//修改username爲HR且狀態爲1的數據
String sql = "update ask_users set email= ? where username = ? AND status = ?";
int rows = template.update(sql, "[email protected]", "HR", 1);
System.out.println("一共修改了" + rows + "行。");
}
//刪除數據
public static void deltet() {
//1.創建一個JdbcTemplate對對象
JdbcTemplate template = new JdbcTemplate(JdbcUtils.getDataSource());
//2.調用方法
//刪除id爲6的數據
int rows = template.update("delete from ask_users where id = ?", 6);
System.out.println("一共刪除了" + rows + "行。");
}
}
二.DBUtils
1.DBUtils的概念:
DBUtils是Apache所提供的一個java語言當中用於操作數據的工具類,小巧簡單且實用;DBUtils他封裝了對JDBC的大部分的操作,簡化了我們操作JDBC的流程
2.DBUtils的三個核心功能:
(1)DBUtils類:主要的功能就是數據的連接進行釋放、關閉、事務的開啓和關閉
(2)QueryRunner:主要的功能就是的JDBC進行一些CRUD操作(最主要的核心類)
(3)ResultSetHandler:主要的功能是對結果集進行處理
3.DML如何操作(update):
(1)導包
commons-dbutils-1.6.jar
(2)創建一個QueryRunner的對象
構造方法:
public QueryRunner():無參,可以不指定數據庫的連接池,一般是用來操作事務
public QueryRunner(DataSource ds):需要指定一個數據庫的連接池,因爲本事並不具備數據
庫的連接功能,所以還是需要第三方的連接池來進行操作。
(3)準備一個sql語句
String sql = "update ask_users set username = ? where id = ?";
(4)準備填充預編譯佔位數據
方式一:使用可變參數
qr.update(sql,"admin","root");
方式二:使用Object[]數組
Object [] obj = {"root","admin"};
int rows = qr.update(sql,obj); / int rows = qr.update(sql,new Object[]{"root","admin"});
注意:
1)這裏返回的int類型的受影響的行數
2)如果沒有預編譯佔位的數據,則直接寫上sql的數據就可以了
3)這種方式適用於增刪改,不適用於查。
例子:
package com.DBUtils;
import com.util.JdbcUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.junit.Test;
import java.sql.SQLException;
public class Demo01 {
public static void main(String[] args) throws SQLException {
}
public void insert() throws SQLException {
//創建一個對象,並指定連接池進行連接
QueryRunner qr = new QueryRunner(JdbcUtils.getDataSource());
//需求新增一條數據
//準備sql
String sql = "insert into ask_users(id,username,password) values(0,?,?)";
//通過可變參數對預編譯的佔位數據進行賦值
//int rows = qr.update(sql,"admin","root");
//通過Object的數組準備參數進行賦值(常用)
Object [] obj = {"root","admin"};
//int rows = qr.update(sql,obj);
//使用匿名數組賦值
int rows = qr.update(sql,new Object[]{"root","admin"});
System.out.println("一共影響了"+rows+"行");
}
@Test
public void update() throws SQLException {
//創建對象並且指定數據源
QueryRunner qr = new QueryRunner(JdbcUtils.getDataSource());
//準備SQL語句
String sql = "update ask_users set username = ? where id = ?";
//執行操作
int rows = qr.update(sql,new Object[]{"toobug",747});
System.out.println("一共影響了"+rows+"行");
}
@Test
public void delete() throws SQLException{
//創建對象並且指定數據源
QueryRunner qr = new QueryRunner(JdbcUtils.getDataSource());
//準備SQL語句
String sql = "delete from ask_users where id = ?";
//執行操作
int rows = qr.update(sql,new Object[]{747});
System.out.println("一共影響了"+rows+"行");
}
}
4.DQL如何操作(query):
所有的查詢的重載一定會有一個ResultSetHandler
ResultSetHandler是對我們的查詢結果進行處理,但是我們發現ResultSetHandler其實是一個接口
ResultSetHandler本身其實針對不同的查詢結果的類型也提供了不同子類給我們進行直接調用
5.ResultSetHandler子類有哪些?
(1)ArrayHandler:將處理的結果的第一條記錄封裝在一個Object數組的集合當中(一般只處理一行數據的查詢)
(2)ArrayListHandler:將處理結果的所有的數據全部封裝在一個Object數組,然後將這個數組在存儲到List的集合當中(一般用於處理多行或者全表的數據)
(3)(重要)BeanHandler:將查詢的一條結果儲存到一個JavaBean的變量當中(一般用於一行數據的查詢)
(4)(重要)BeanListHandler:將處理結果的所有的數據全部全部存儲在JavaBean當中,然後將這些JavaBean在存儲到List的集合當中(一般用於處理多行或者全表的數據)
(5)ColumnListHandler:查詢指定行的數據(不包含列名),存在一個List集合
(6)MapListHandler:會將我們結果的所有數據全部封裝在一個Map集合當中,key就對應列名,value就對應了列的值,因爲存在多個,所以繼續封裝在List集合當中
(7)(重要)ScalarHandler:將單個數據(非行)查詢並且返回(只用於聚合函數)
例子:
package com.DBUtils;
import com.util.JdbcUtils;
import com.vo.UserVO;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.*;
import org.junit.Test;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
public class Demo02 {
//創建對象
QueryRunner qr = new QueryRunner();
@Test
//ArrayHandler:將處理的結果的第一條記錄的數據值封裝在一個Object數組的集合當中(一般只處理一行數據的查詢)
public void arrayHandler() throws SQLException {
//創建對象
QueryRunner qr = new QueryRunner(JdbcUtils.getDataSource());
//準備sql
String sql = "select * from ask_users";
//執行查詢
Object[] obj = qr.query(sql,new ArrayHandler());
//運行查詢結果
for(Object o : obj){
System.out.println(o);
}
}
@Test
//ArrayListHandler:將處理結果的所有的數據的值全部封裝在一個Object數組,然後將這個數組在存儲到List的集合當中(一般用於處理多行或者全表的數據)
public void arrayListHandler() throws SQLException{
String sql = "select * from ask_users";
List<Object[]> list = qr.query(sql,new ArrayListHandler());
for(Object[] objs : list){
for(Object o : objs){
System.out.println(o);
}
System.out.println("-------------------------");
}
}
@Test
//(重要)BeanHandler:將查詢的第一條結果儲存到一個JavaBean的對應變量當中(一般用於一行數據的查詢,這裏因爲是自動裝配
// 所以一定要保證JavaBean的字段和數據庫的字段名完全一致 是原則上也應該如此)
public void beanHandler() throws SQLException{
String sql = "select * from ask_users";
UserVO userVO = qr.query(sql,new BeanHandler<UserVO>(UserVO.class));
System.out.println(userVO.getUsername());
}
@Test
//(重要)BeanListHandler:將處理結果的所有的數據全部全部存儲在JavaBean當中,然後將這些JavaBean在存儲到List的集合當中(一般用於處理多行或者全表的數據)
public void beanListHandler() throws SQLException{
String sql = "select * from ask_users";
List<UserVO> userVOSList = qr.query(sql,new BeanListHandler<UserVO>(UserVO.class));
userVOSList.forEach(System.out::println);
}
@Test
//ColumnListHandler(String 列名):查詢指定列的數據(不包含列名),存在一個List集合
public void columnListHandler() throws SQLException{
String sql = "select * from ask_users";
List<String> list = qr.query(sql,new ColumnListHandler<String>("username"));
list.forEach(System.out::println);
}
@Test
//MapListHandler:會將我們結果的所有數據全部封裝在一個Map集合當中,key就對應列名,value就對應了列的值,因爲存在多個,所以繼續封裝在List集合當中
public void mapListHandler() throws SQLException{
String sql = "select * from ask_users";
List<Map<String,Object>> list = qr.query(sql,new MapListHandler());
list.forEach(System.out::println);
}
@Test
//ScalarHandler:將單個數據(非行)查詢並且返回(只用於聚合函數)
public void scalarHandler() throws SQLException {
String sql = "select count(id) from ask_users";
Object obj = qr.query(sql,new ScalarHandler());
System.out.println(obj);
}
@Test
//query的多個參數的填充(數據源,sql語句,填充參數,實現類對象)
public void beanListHandlers() throws SQLException{
String sql = "select * from ask_users where gender = ?";
//List<UserVO> userVOSList = qr.query(sql,1,new BeanListHandler<UserVO>(UserVO.class));
List<UserVO> userVOSList = qr.query(JdbcUtils.getC3p0Pool(),sql,new Object[]{1},new BeanListHandler<UserVO>(UserVO.class));
userVOSList.forEach(System.out::println);
}
}