1. JdbcTemplate
概念: 封装一个自定义的 JdbcTemplate 类,负责获取数据源,以及封装各种类型的SQL语句的执行方法:
流程:
- 通过
DriverManager创建一个连接实例connection。 - 通过
connection创建一个SQL媒介实例statement,负责运输SQL语句到数据库,执行并且拿回结果。- 如果是查询操作,会返回一个
ResutlSet结果集。 - 如果是其他操作,会返回一个影响的条目数。
- 如果是查询操作,会返回一个
- 解析
ResutlSet结果集:- 多条结果集可以解析成一个
List<Map>或者List<Pojo>结构。 - 单条的结果可以解析成一个
Map<String, Object>结构。 - 单条的结果可以解析成一个
Pojo结构。
- 多条结果集可以解析成一个
- 释放资源,关闭连接。
查询流程图
2. DDL-execute()
概念: boolean execute(String sql) 用于执行DDL操作,如造表,造索引等,该方法接收一个完整的SQL语句,并返回一个 boolean 类型的结果。
流程:
- 通过
dataSource实例获取一个连接实例connection:Connection getConnection()
- 通过连接实例
connection,获取一个Statement类型的SQL媒介实例statement:Statement createStatement()
- 通过SQL媒介实例
statement将SQL发送到数据库,执行并得到boolean类型的结果:boolean execute(String sql):结果只有是ResultSet对象时才返回true。
- 封装一个
closeStatement(Statement statement)负责释放资源:- 如果资源不为null,就直接调用资源的
close()进行关闭。
- 如果资源不为null,就直接调用资源的
- 通过
dataSource实例关闭当前连接:void closeConnection(Connection connection)
3. DML-update()
概念: int[] batchUpdate(String sql, Object[]... params) 用于执行DML操作,如增,删,改数据操作,该方法接收一个包含占位符的SQL语句和对应占位符的参数列表,返回int类型结果表示本次操作所影响的条目数。
流程:
- 通过
dataSource实例获取一个连接实例connection:Connection getConnection()
- 通过连接实例
connection,获取一个PrepareStatement类型的SQL媒介实例prepareStatement:PreparedStatement prepareStatement(String sql):获取的同时需要绑定SQL。
- 封装一个
sendSqlAndGetInt()负责为SQL中的问号赋值,以及发送SQL,并拿回int类型结果:void setObject(int i, Object x):第i个问号赋值x,i从1开始。int executeUpdate():通过媒介将SQL发送到数据库,执行并得到结果。
- 封装一个
closeStatement(Statement statement)负责释放资源:- 如果资源不为null,就直接调用资源的
close()进行关闭。
- 如果资源不为null,就直接调用资源的
- 通过
dataSource实例关闭当前连接:void closeConnection(Connection connection)
4. DML-batchUpdate()
概念: int[] batchUpdate() 用于执行批量DML操作,如批增,批删,批改等。
4.1 批处理同类型SQL
概念: int[] batchUpdate(String sql, Object[]... params) 负责批量处理多条相同类型的SQL,需要设置事务保护,返回批量DML操作的影响条目数数组。
流程:
- 通过
dataSource实例获取一个连接实例connection:Connection getConnection()
- 通过连接实例
connection,获取一个PrepareStatement类型的SQL媒介实例prepareStatement:PreparedStatement prepareStatement(String sql):获取的同时需要绑定SQL。
- 关闭连接实例
connection的自动提交属性:void setAutoCommit(boolean autoCommit):默认为true。
- 封装一个
sendSqlAndGetIntArray()负责为每条SQL中的问号赋值,以及发送SQL,并拿回int[]类型结果:void setObject(int i, Object x):第i个问号赋值x,i从1开始。int addBatch():将拼装完整的SQL语句加入到预执行区域,等待executeBatch()。int[] executeBatch():将预执行区域中的所有SQL语句发送到数据库,执行并返回int[]类型的结果。
- 通过连接实例
connection,手动提交或者回滚本次操作:void commit()void rollback():在异常捕捉中进行处理。
- 在异常处理的
finally块中,将自动提交属性还原。void setAutoCommit(boolean autoCommit):默认为true。
- 封装一个
closeStatement(Statement statement)负责释放资源:- 如果资源不为null,就直接调用资源的
close()进行关闭。
- 如果资源不为null,就直接调用资源的
- 通过
dataSource实例关闭当前连接:void closeConnection(Connection connection)
4.2 批处理不同类型SQL
概念: int[] batchUpdate(String... sqls) 负责批量处理多条不同类型的SQL,需要设置事务保护,该方法需要传入一个完整SQL的数组,返回批量DML操作的影响条目数数组。
流程:
- 通过
dataSource实例获取一个连接实例connection:Connection getConnection()
- 通过连接实例
connection,获取一个Statement类型的SQL媒介实例statement:Statement createStatement()
- 关闭连接实例
connection的自动提交属性:void setAutoCommit(boolean autoCommit):默认为true。
- 封装一个
sendSqlAndGetIntArray()负责将每条SQL添加到预执行区域,然后一起提交执行:void addBatch(String sql):将SQL语句加入到预执行区域,等待executeBatch()。int[] executeBatch():将预执行区域中的所有SQL语句发送到数据库,执行并返回int[]类型的结果。
- 通过连接实例
connection,手动提交或者回滚本次操作:void commit()void rollback():在异常捕捉中进行处理。
- 在异常处理的
finally块中,将自动提交属性还原。void setAutoCommit(boolean autoCommit):默认为true。
- 封装一个
closeStatement(Statement statement)负责释放资源:- 如果资源不为null,就直接调用资源的
close()进行关闭。
- 如果资源不为null,就直接调用资源的
- 通过
dataSource实例关闭当前连接:void closeConnection(Connection connection)
5. DQL-queryForList()
概念: List<Map<String, Object>> queryForList(String sql, Object... params) 用于多行信息查询,该方法接收一个包含占位符的SQL语句和对应占位符的参数列表,返回 List<Map> 结构的结果集。
流程:
- 通过
dataSource实例获取连接:Connection getConnection()
- 通过连接实例
connection,获取一个PrepareStatement类型的SQL媒介实例prepareStatement:PreparedStatement prepareStatement(String sql):获取的同时需要绑定SQL。
- 封装一个
sendSqlAndGetResultSet()负责为SQL中的问号赋值,以及发送SQL,并拿回结果:void setObject(int i, Object x):第i个问号赋值x,i从1开始。ResultSet executeQuery():通过媒介将SQL发送到数据库,执行并得到ResultSet结果集。
- 封装一个
changeResultSetToList(),负责将ResultSet转化为List<Map>结构:ResultSetMetaData getMetaData():通过ResultSet对象获取元数据。int getColumnCount():通过ResultSetMetaData对象获取表的总列数。String getColumnName(int column):通过ResultSetMetaData对象获取指定索引的列名,从1开始。Object getObject(String columnLabel):通过ResultSet对象获取对应列名的值。
- 封装一个
closeResultSet(ResultSet resultSet)负责释放资源:- 如果资源不为null,就直接调用资源的
close()进行关闭。
- 如果资源不为null,就直接调用资源的
- 封装一个
closeStatement(Statement statement)负责释放资源:- 如果资源不为null,就直接调用资源的
close()进行关闭。
- 如果资源不为null,就直接调用资源的
- 通过
dataSource实例关闭连接:void closeConnection(Connection connection)
6. DQL-queryForMap()
概念: Map<String, Object> queryForMap(String sql, Object... params) 用于单行信息查询,该方法接收一个包含占位符的SQL语句和对应占位符的参数列表,返回 Map 结构的结果集。
流程:
- 调用
queryForList()获得唯一一行数据。 - 如果数据正常,取出
List中的唯一一条数据并返回。 - 如果数据异常,返回一个空Map实例。
7. DQL-queryForInt()
概念: int queryForInt(String sql, Object... params) 用于数据数量查询,该方法接收一个包含占位符的SQL语句和对应占位符的参数列表,返回int类型的结果。
流程:
- 调用
queryForMap()获得包含数量信息的Map结果。 - 如果数据正常,取出
Map中的结果并转成int类型。 - 如果数据异常,返回-1。
整体代码
源码: jdbc/JdbcTemplate
package com.yap.jdbc;
import com.yap.factory.DataSource;
import com.yap.factory.DataSourceFactory;
import java.sql.*;
import java.util.*;
/**
* @author yap
*/
public class JdbcTemplate {
private DataSource dataSource = DataSourceFactory.getDataSource();
public boolean execute(String sql) {
boolean result = false;
Connection connection = null;
Statement statement = null;
try {
connection = dataSource.getConnection();
statement = connection.createStatement();
result = statement.execute(sql);
} catch (SQLException e) {
e.printStackTrace();
} finally {
closeStatement(statement);
dataSource.closeConnection(connection);
}
return result;
}
public int update(String sql, Object... params) {
Connection connection = null;
PreparedStatement prepareStatement = null;
int result = -1;
try {
connection = dataSource.getConnection();
prepareStatement = connection.prepareStatement(sql);
result = sendSqlAndGetInt(prepareStatement, params);
} catch (SQLException e) {
e.printStackTrace();
} finally {
closeStatement(prepareStatement);
dataSource.closeConnection(connection);
}
return result;
}
public int[] batchUpdate(String sql, Object[]... params) {
Connection connection = null;
PreparedStatement prepareStatement = null;
int[] result = null;
try {
connection = dataSource.getConnection();
connection.setAutoCommit(false);
prepareStatement = connection.prepareStatement(sql);
result = sendSqlAndGetIntArray(prepareStatement, params);
connection.commit();
} catch (SQLException e) {
try {
connection.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();
} finally {
try {
if (connection != null) {
connection.setAutoCommit(true);
}
} catch (SQLException e) {
e.printStackTrace();
}
closeStatement(prepareStatement);
dataSource.closeConnection(connection);
}
return result;
}
public int[] batchUpdate(String... sqls) {
Connection connection = null;
Statement statement = null;
int[] result = null;
try {
connection = dataSource.getConnection();
connection.setAutoCommit(false);
statement = connection.createStatement();
result = sendSqlAndGetIntArray(statement, sqls);
connection.commit();
} catch (SQLException e) {
try {
connection.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();
} finally {
try {
if (connection != null) {
connection.setAutoCommit(true);
}
} catch (SQLException e) {
e.printStackTrace();
}
closeStatement(statement);
dataSource.closeConnection(connection);
}
return result;
}
public List<Map<String, Object>> queryForList(String sql, Object... params) {
List<Map<String, Object>> result = new ArrayList<>();
Connection connection = null;
PreparedStatement prepareStatement = null;
ResultSet resultSet = null;
try {
connection = dataSource.getConnection();
prepareStatement = connection.prepareStatement(sql);
resultSet = sendSqlAndGetResultSet(prepareStatement, params);
result = changeResultSetToList(resultSet);
} catch (SQLException e) {
e.printStackTrace();
} finally {
closeResultSet(resultSet);
closeStatement(prepareStatement);
dataSource.closeConnection(connection);
}
return result;
}
public Map<String, Object> queryForMap(String sql, Object... params) {
Map<String, Object> resultMap = new HashMap<>(10);
List<Map<String, Object>> list = queryForList(sql, params);
if (!list.isEmpty()) {
resultMap = list.get(0);
}
return resultMap;
}
public int queryForInt(String sql, Object... params) {
int result = -1;
Map<String, Object> map = queryForMap(sql, params);
Object value = null;
for (String key : map.keySet()) {
value = map.get(key);
break;
}
if (value != null) {
result = Integer.parseInt(value.toString());
}
return result;
}
private int[] sendSqlAndGetIntArray(Statement statement, String... sqls) throws SQLException {
for (String sql : sqls) {
statement.addBatch(sql);
}
return statement.executeBatch();
}
private int sendSqlAndGetInt(PreparedStatement prepareStatement, Object... params) throws SQLException {
for (int i = 0, j = params.length; i < j; i++) {
prepareStatement.setObject(i + 1, params[i]);
}
return prepareStatement.executeUpdate();
}
private int[] sendSqlAndGetIntArray(PreparedStatement prepareStatement, Object[]... params) throws SQLException {
for (Object[] param : params) {
for (int i = 0, j = param.length; i < j; i++) {
prepareStatement.setObject(i + 1, param[i]);
}
prepareStatement.addBatch();
}
return prepareStatement.executeBatch();
}
private ResultSet sendSqlAndGetResultSet(PreparedStatement prepareStatement, Object... params) throws SQLException {
for (int i = 0, j = params.length; i < j; i++) {
prepareStatement.setObject(i + 1, params[i]);
}
return prepareStatement.executeQuery();
}
private List<Map<String, Object>> changeResultSetToList(ResultSet resultSet) throws SQLException {
List<Map<String, Object>> resultList = new ArrayList<>();
ResultSetMetaData metaData = resultSet.getMetaData();
int columnCount = metaData.getColumnCount();
Map<String, Object> tempMap;
// rows
while (resultSet.next()) {
tempMap = new HashMap<>(10);
// columns in row, iter from 1
for (int i = 1; i <= columnCount; i++) {
String columnName = metaData.getColumnName(i);
Object value = resultSet.getObject(columnName);
tempMap.put(columnName, value);
}
resultList.add(tempMap);
}
return resultList;
}
private void closeStatement(Statement statement) {
try {
if (statement != null) {
statement.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
private void closeResultSet(ResultSet resultSet) {
try {
if (resultSet != null) {
resultSet.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
源码: test/JdbcTemplateTest
package com.yap.test;
import com.yap.jdbc.JdbcTemplate;
import org.junit.Test;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
/**
* @author yap
*/
public class JdbcTemplateTest {
private JdbcTemplate jdbcTemplate = new JdbcTemplate();
@Test
public void execute() {
String sql = "CREATE TABLE `JDBC` (" +
"`ID` INT AUTO_INCREMENT PRIMARY KEY ," +
"`NAME` VARCHAR(50) NOT NULL) " +
"ENGINE = INNODB DEFAULT CHARSET UTF8MB4";
System.out.println(jdbcTemplate.execute(sql));
}
@Test
public void insert() {
String sql = "INSERT INTO `JDBC` (`NAME`) VALUES (?)";
System.out.println(jdbcTemplate.update(sql, "zhaosi"));
}
@Test
public void update() {
String sql = "UPDATE `JDBC` SET `NAME` = ? WHERE `ID` = ?";
System.out.println(jdbcTemplate.update(sql, "liuneng", 1));
}
@Test
public void delete() {
String sql = "DELETE FROM `JDBC` WHERE `ID` = ?";
System.out.println(jdbcTemplate.update(sql, 1));
}
@Test
public void batchInsertWithSameSql() {
String sql = "INSERT INTO `JDBC` (`NAME`) VALUES (?)";
Object[] param01 = {"zhaosi"};
Object[] param02 = {"liuneng"};
Object[] param03 = {"guangkun"};
int[] result = jdbcTemplate.batchUpdate(sql, param01, param02, param03);
System.out.println(Arrays.toString(result));
}
@Test
public void batchUpdateWithSameSql() {
String sql = "UPDATE `JDBC` SET `NAME` = ? WHERE `ID` = ?";
Object[] param01 = {"zhaosi2", 3};
Object[] param02 = {"liuneng2", 4};
Object[] param03 = {"guangkun2", 5};
int[] result = jdbcTemplate.batchUpdate(sql, param01, param02, param03);
System.out.println(Arrays.toString(result));
}
@Test
public void batchDeleteWithSameSql() {
String sql = "DELETE FROM `JDBC` WHERE `ID` = ?";
Object[] param01 = {3};
Object[] param02 = {4};
Object[] param03 = {5};
int[] result = jdbcTemplate.batchUpdate(sql, param01, param02, param03);
System.out.println(Arrays.toString(result));
}
@Test
public void batchUpdateWithDifferentSql() {
String insertSql = "INSERT INTO `JDBC` (`NAME`) VALUES ('FEIJI')";
String updateSql = "UPDATE `JDBC` SET `NAME` = 'DAPAO' WHERE `NAME` = 'FEIJI'";
String[] sqls = {insertSql, updateSql};
int[] result = jdbcTemplate.batchUpdate(sqls);
System.out.println(Arrays.toString(result));
}
@Test
public void queryForList() {
String sql = "SELECT * FROM EMP WHERE ENAME != ? AND SAL > ?";
List<Map<String, Object>> list = jdbcTemplate.queryForList(sql, "SMITH", 1500);
for (Map<String, Object> map : list) {
System.out.println(map);
}
}
@Test
public void queryForMap() {
String sql = "SELECT * FROM EMP WHERE EMPNO = ?";
Map<String, Object> map = jdbcTemplate.queryForMap(sql, 7654);
System.out.println(map);
}
@Test
public void queryForInt() {
String sql = "SELECT COUNT(`ID`) FROM JDBC WHERE ID > ?";
System.out.println(jdbcTemplate.queryForInt(sql,8));
}
}