记录:289
场景:基于Spring Boot应用JdbcTemplate操作数据库。包括查、增、改、删操作。对应SQL关键字是select、insert into、update、delete。
版本:
Spring Boot 2.6.3
Spring Framework 5.3.15
MySQL 5.7.33
JDK 1.8
名词:
JDBC:即Java DataBase Connectivity的缩写,它是Java程序访问数据库的标准接口。
目的:
便于查阅和窥探JdbcTemplate的查、增、改、删操作。清楚描述一个函数,了解函数入参类型,了解返回值类型,应该就可以参透这个函数,至少应用层面是没问题。
一、查
查,即使用JdbcTemplate对数据库的数据做查询操作。
SQL关键字:select。
1.query函数
1.1 query函数定义
参数sql:数据库执行的SQL语句。
参数rowMapper:是RowMapper接口实现类,把数据库返回的结果集表字段与值,封装成自定义的JavaBean对象。
参数args:是SQL中有占位符?时,传入变量的方式。
参数argTypes:是args传入参数对应的数据库表字段的数据类型。
public <T> List<T> query(String sql, RowMapper<T> rowMapper);
public <T> List<T> query(String sql, RowMapper<T> rowMapper, @Nullable Object... args);
public <T> List<T> query(String sql, Object[] args, int[] argTypes, RowMapper<T> rowMapper);
1.2 query使用场景
场景:使用query函数,可以把查询结果集按照自定义的JavaBean封装,并以List方式返回查询结果集。
1.3 query使用举例
/**
* 1.query函数入参不带查询条件,如有查询条件直接写在SQL中
* 2.使用自定义CityRowMapper封装返回值
* 3.使用java.util.stream.Stream遍历结果
*/
public static void f1_1() {
// 1.获取查询sql
String sql = getSelectSql01();
// 2.获取JdbcTemplate
JdbcTemplate jt = getJdbcTemplate();
// 3.查询数据集
List<CityPO> list = jt.query(sql, new CityRowMapper());
// 4.遍历结果并打印
Stream<CityPO> stream = list.stream().parallel();
stream.forEach(cityPO -> {
System.out.println(cityPO.toString());
});
}
/**
* 1.query函数入参带查询条件
* 2.使用自定义CityRowMapper封装返回值
* 3.使用java.util.stream.Stream遍历结果
*/
public static void f1_2() {
// 1.获取查询sql
String sql = getSelectSql02();
// 2.获取JdbcTemplate
JdbcTemplate jt = getJdbcTemplate();
// 3.组装查询条件
Object[] args = new Object[]{"杭州", "1"};
// 4.查询数据集
List<CityPO> list = jt.query(sql, new CityRowMapper(), args);
// 5.遍历结果并打印
Stream<CityPO> stream = list.stream().parallel();
stream.forEach(cityPO -> {
System.out.println(cityPO.toString());
});
}
/**
* 1.query函数入参带查询条件,入参带参数类型
* 2.使用自定义CityRowMapper封装返回值
* 3.使用java.util.stream.Stream遍历结果
*/
public static void f1_3() {
// 1.获取查询sql
String sql = getSelectSql02();
// 2.获取JdbcTemplate
JdbcTemplate jt = getJdbcTemplate();
// 3.组装查询条件
Object[] args = new Object[]{"杭州", "1"};
int[] argTypes = new int[]{Types.VARCHAR, Types.BIGINT};
// 4.查询数据集
List<CityPO> list = jt.query(sql, args, argTypes, new CityRowMapper());
// 5.遍历结果并打印
Stream<CityPO> stream = list.stream().parallel();
stream.forEach(cityPO -> {
System.out.println(cityPO.toString());
});
}
/**
* 1.query函数入参带查询条件
* 2.使用BeanPropertyRowMapper封装返回值
* 3.使用java.util.stream.Stream遍历结果
*/
public static void f1_4() {
// 1.获取查询sql
String sql = getSelectSql02();
// 2.获取JdbcTemplate
JdbcTemplate jt = getJdbcTemplate();
// 3.组装查询条件
Object[] args = new Object[]{"杭州", "1"};
// 4.查询数据集
List<CityPO> list = jt.query(sql, new BeanPropertyRowMapper<>(CityPO.class), args);
// 5.遍历结果并打印
Stream<CityPO> stream = list.stream().parallel();
stream.forEach(cityPO -> {
System.out.println(cityPO.toString());
});
}
/**
* 1.select语句
* 2.query函数入参不带查询条件
*/
public static String getSelectSql01() {
String sql01 = "SELECT\n" +
" ID,CITY_NAME,LAND_AREA,POPULATION,GROSS,\n" +
" CITY_DESCRIBE,DATA_YEAR,UPDATE_TIME\n" +
"FROM t_city ";
return sql01.toString();
}
/**
* 1.select语句
* 2.query函数入参带查询条件
*/
public static String getSelectSql02() {
String sql02 = "SELECT\n" +
" ID,CITY_NAME,LAND_AREA,POPULATION,GROSS,\n" +
" CITY_DESCRIBE,DATA_YEAR,UPDATE_TIME\n" +
"FROM t_city " +
"WHERE CITY_NAME = ? AND ID =? ";
return sql02.toString();
}
2.queryForStream函数
2.1 queryForStream函数定义
Stream,即java.util.stream.Stream,这个接口有点意思,值得花时间研究一下。
参数sql:数据库执行的SQL语句。
参数rowMapper:是RowMapper接口实现类,把数据库返回的结果集表字段与值,封装成自定义的JavaBean对象。
参数args:是SQL中有占位符?时,传入变量的方式。
参数argTypes:是args传入参数对应的数据库表字段的数据类型。
参数pss: 封装入参。
public <T> Stream<T> queryForStream(String sql, RowMapper<T> rowMapper);
public <T> Stream<T> queryForStream(String sql, RowMapper<T> rowMapper, @Nullable Object... args);
public <T> Stream<T> queryForStream(String sql, @Nullable PreparedStatementSetter pss, RowMapper<T> rowMapper);
2.2 queryForStream使用场景
场景:使用queryForStream函数,可以把查询结果集按照自定义的JavaBean封装,并以Stream方式返回查询结果集。
2.3 queryForStream使用举例
/**
* 1.queryForStream函数入参不带查询条件,如有查询条件直接写在SQL中
* 2.使用自定义CityRowMapper封装返回值
* 3.使用java.util.stream.Stream遍历结果
*/
public static void f2_1() {
// 1.获取查询sql
String sql = getSelectSql01();
// 2.获取JdbcTemplate
JdbcTemplate jt = getJdbcTemplate();
// 3.查询数据集
Stream<CityPO> stream = jt.queryForStream(sql, new CityRowMapper());
// 4.遍历结果并打印
stream.forEach(cityPO -> {
System.out.println(cityPO.toString());
});
}
/**
* 1.queryForStream函数入参带查询条件
* 2.使用自定义CityRowMapper封装返回值
* 3.使用java.util.stream.Stream遍历结果
*/
public static void f2_2() {
// 1.获取查询sql
String sql = getSelectSql02();
// 2.获取JdbcTemplate
JdbcTemplate jt = getJdbcTemplate();
// 3.组装查询条件
Object[] args = new Object[]{"杭州", "1"};
// 4.查询数据集
Stream<CityPO> stream = jt.queryForStream(sql, new CityRowMapper(), args);
// 5.遍历结果并打印
stream.forEach(cityPO -> {
System.out.println(cityPO.toString());
});
}
/**
* 1.queryForStream函数入参带查询条件
* 2.使用自定义CityRowMapper封装返回值
* 3.使用java.util.stream.Stream遍历结果
*/
public static void f2_3() {
// 1.获取查询sql
String sql = getSelectSql02();
// 2.获取JdbcTemplate
JdbcTemplate jt = getJdbcTemplate();
// 3.组装查询条件
Object[] args = new Object[]{"杭州", "1"};
// 4.查询数据集
Stream<CityPO> stream = jt.queryForStream(sql, new ArgumentPreparedStatementSetter(args), new CityRowMapper());
// 5.遍历结果并打印
stream.forEach(cityPO -> {
System.out.println(cityPO.toString());
});
}
/**
* 1.select语句
* 2.query函数入参不带查询条件
* 3.queryForStream函数入参不带查询条件
*/
public static String getSelectSql01() {
String sql01 = "SELECT\n" +
" ID,CITY_NAME,LAND_AREA,POPULATION,GROSS,\n" +
" CITY_DESCRIBE,DATA_YEAR,UPDATE_TIME\n" +
"FROM t_city ";
return sql01.toString();
}
/**
* 1.select语句
* 2.query函数入参带查询条件
* 3.queryForStream函数入参带查询条件
*/
public static String getSelectSql02() {
String sql02 = "SELECT\n" +
" ID,CITY_NAME,LAND_AREA,POPULATION,GROSS,\n" +
" CITY_DESCRIBE,DATA_YEAR,UPDATE_TIME\n" +
"FROM t_city " +
"WHERE CITY_NAME = ? AND ID =? ";
return sql02.toString();
}
3.queryForMap函数
3.1 queryForMap函数定义
结果集封装在一个Map中,即返回一条记录。
public Map<String, Object> queryForMap(String sql);
public Map<String, Object> queryForMap(String sql, @Nullable Object... args);
public Map<String, Object> queryForMap(String sql, Object[] args, int[] argTypes);
3.2 queryForMap使用场景
场景:使用queryForMap函数,可以把查询结果集封装成Map<String, Object>,而且只能查询一条记录,即数据库表中一行数据。
3.3 queryForMap使用举例
/**
* 1.queryForMap函数入参不带查询条件,如有查询条件直接写在SQL中
* 2.查询条件中只能限定一条记录,返回结果封装在Map中
* 3.使用java.util.stream.Stream遍历结果
*/
public static void f3_1() {
// 1.获取查询sql
String sql = getSelectSql03();
// 2.获取JdbcTemplate
JdbcTemplate jt = getJdbcTemplate();
// 3.查询数据集
Map<String, Object> map = jt.queryForMap(sql);
// 4.遍历结果并打印
Stream<Map.Entry<String, Object>> stream = map.entrySet().stream();
stream.forEach(cityPO -> {
System.out.println(cityPO.getKey() + " = " + cityPO.getValue());
});
}
/**
* 1.queryForMap函数入参带查询条件
* 2.查询条件中只能限定一条记录,返回结果封装在Map中
* 3.使用map.forEach遍历结果
*/
public static void f3_2() {
// 1.获取查询sql
String sql = getSelectSql04();
// 2.获取JdbcTemplate
JdbcTemplate jt = getJdbcTemplate();
// 3.组装查询条件
Object[] args = new Object[]{"杭州", "1"};
// 4.查询数据集
Map<String, Object> map = jt.queryForMap(sql, args);
// 5.遍历结果并打印
map.forEach((key, value) -> {
System.out.println(key + " = " + value.toString());
});
}
/**
* 1.queryForMap函数入参带查询条件,入参带参数类型
* 2.查询条件中只能限定一条记录,返回结果封装在Map中
* 3.使用Map.Entry遍历结果
*/
public static void f3_3() {
// 1.获取查询sql
String sql = getSelectSql04();
// 2.获取JdbcTemplate
JdbcTemplate jt = getJdbcTemplate();
// 3.组装查询条件
Object[] args = new Object[]{"杭州", "1"};
int[] argTypes = new int[]{Types.VARCHAR, Types.BIGINT};
// 4.查询数据集
Map<String, Object> map = jt.queryForMap(sql, args, argTypes);
// 5.遍历结果并打印
for (Map.Entry<String, Object> entry : map.entrySet()) {
System.out.println(entry.getKey() + " = " + entry.getValue());
}
}
/**
* 1.select语句,查一条数据
* 2.queryForMap函数入参不带查询条件
*/
public static String getSelectSql03() {
String sql03 = "SELECT\n" +
" ID,CITY_NAME,LAND_AREA,POPULATION,GROSS,\n" +
" CITY_DESCRIBE,DATA_YEAR,UPDATE_TIME\n" +
"FROM t_city limit 1";
return sql03.toString();
}
/**
* 1.select语句,查一条数据
* 2.queryForMap函数入参带查询条件
*/
public static String getSelectSql04() {
String sql04 = "SELECT\n" +
" ID,CITY_NAME,LAND_AREA,POPULATION,GROSS,\n" +
" CITY_DESCRIBE,DATA_YEAR,UPDATE_TIME\n" +
"FROM t_city " +
"WHERE CITY_NAME = ? AND ID =? limit 1";
return sql04.toString();
}
4.queryForRowSet函数
4.1 queryForRowSet函数定义
queryForRowSet把结果封装成SqlRowSet,需要根据SqlRowSet的next()去遍历函数取值。
不能直接取值否则报错:Caused by: java.sql.SQLException: 光标位置无效。
需要调用调用SqlRowSet.next()后,内部会调用结果集ResultSet的结果索引值,才能遍历取值。
参数sql:数据库执行的SQL语句。
参数args:是SQL中有占位符?时,传入变量的方式。
参数argTypes:是args传入参数对应的数据库表字段的数据类型。
public SqlRowSet queryForRowSet(String sql);
public SqlRowSet queryForRowSet(String sql, @Nullable Object... args);
public SqlRowSet queryForRowSet(String sql, Object[] args, int[] argTypes);
4.2 queryForRowSet使用场景
场景:使用queryForRowSet函数,结果集封装成SqlRowSet,需要额外去遍历结果集取值。
4.3 queryForRowSet使用举例
/**
* 1.queryForRowSet函数入参不带查询条件,如有查询条件直接写在SQL中
* 2.使用SqlRowSet封装返回值
* 3.使用sqlRowSet.next()遍历结果
* 4.直接取值报错: Caused by: java.sql.SQLException: 光标位置无效
* 5.调用SqlRowSet.next()后,取值,内部会调用结果集ResultSet的结果索引值即可以取值
*/
public static void f4_1() {
// 1.获取查询sql
String sql = getSelectSql01();
// 2.获取JdbcTemplate
JdbcTemplate jt = getJdbcTemplate();
jt.setFetchSize(2);
// 3.查询数据集
SqlRowSet sqlRowSet = jt.queryForRowSet(sql);
// 4.遍历结果并打印
while (sqlRowSet.next()) {
Object result = sqlRowSet.getObject("CITY_NAME");
System.out.println(result);
}
}
/**
* 1.queryForRowSet函数入参带查询条件
* 2.使用SqlRowSet封装返回值
* 3.使用sqlRowSet.next()遍历结果
* 4.直接取值报错: Caused by: java.sql.SQLException: 光标位置无效
* 5.调用SqlRowSet.next()后,取值,内部会调用结果集ResultSet的结果索引值即可以取值
*/
public static void f4_2() {
// 1.获取查询sql
String sql = getSelectSql02();
// 2.获取JdbcTemplate
JdbcTemplate jt = getJdbcTemplate();
// 3.组装查询条件
Object[] args = new Object[]{"杭州", "1"};
// 4.查询数据集
SqlRowSet sqlRowSet = jt.queryForRowSet(sql, args);
// 5.遍历结果并打印
while (sqlRowSet.next()) {
Object result = sqlRowSet.getObject("CITY_DESCRIBE");
System.out.println(result);
}
}
/**
* 1.queryForRowSet函数入参带查询条件,入参带参数类型
* 2.使用SqlRowSet封装返回值
* 3.使用sqlRowSet.next()遍历结果
* 4.直接取值报错: Caused by: java.sql.SQLException: 光标位置无效
* 5.调用SqlRowSet.next()后,取值,内部会调用结果集ResultSet的结果索引值即可以取值
*/
public static void f4_3() {
// 1.获取查询sql
String sql = getSelectSql02();
// 2.获取JdbcTemplate
JdbcTemplate jt = getJdbcTemplate();
// 3.组装查询条件
Object[] args = new Object[]{"杭州", "1"};
int[] argTypes = new int[]{Types.VARCHAR, Types.BIGINT};
// 4.查询数据集
SqlRowSet sqlRowSet = jt.queryForRowSet(sql, args, argTypes);
// 5.遍历结果并打印
while (sqlRowSet.next()) {
Object result = sqlRowSet.getObject("DATA_YEAR");
System.out.println(result);
}
}
/**
* 1.select语句
* 2.query函数入参不带查询条件
* 3.queryForStream函数入参不带查询条件
* 4.queryForRowSet函数入参不带查询条件
*/
public static String getSelectSql01() {
String sql01 = "SELECT\n" +
" ID,CITY_NAME,LAND_AREA,POPULATION,GROSS,\n" +
" CITY_DESCRIBE,DATA_YEAR,UPDATE_TIME\n" +
"FROM t_city ";
return sql01.toString();
}
/**
* 1.select语句
* 2.query函数入参带查询条件
* 3.queryForStream函数入参带查询条件
* 4.queryForRowSet函数入参带查询条件
*/
public static String getSelectSql02() {
String sql02 = "SELECT\n" +
" ID,CITY_NAME,LAND_AREA,POPULATION,GROSS,\n" +
" CITY_DESCRIBE,DATA_YEAR,UPDATE_TIME\n" +
"FROM t_city " +
"WHERE CITY_NAME = ? AND ID =? ";
return sql02.toString();
}
5.queryForObject函数
5.1 queryForObject查询一个字段
5.1.1 queryForObject函数定义
queryForObject的以下3个函数,查询一个字段值。
参数sql:数据库执行的SQL语句。
参数requiredType:封装返回值类型。
参数args:是SQL中有占位符?时,传入变量的方式。
参数argTypes:是args传入参数对应的数据库表字段的数据类型。
public <T> T queryForObject(String sql, Class<T> requiredType);
public <T> T queryForObject(String sql, Class<T> requiredType, @Nullable Object... args);
public <T> T queryForObject(String sql, Object[] args, int[] argTypes, Class<T> requiredType);
5.1.2 queryForObject使用场景
场景:使用queryForObject函数,查询一条记录的一个字段值,根据基本类型封装返回值。
5.1.3 queryForObject使用举例
/**
* 1.queryForObject函数入参不带查询条件,如有查询条件直接写在SQL中
* 2.根据基本类型封装返回值
* 3.查询一条记录的一个字段值
*/
public static void f5_1_1() {
// 1.获取查询sql
String sql = getSelectSql05();
// 2.获取JdbcTemplate
JdbcTemplate jt = getJdbcTemplate();
// 3.查询数据集
String cityName = jt.queryForObject(sql, String.class);
// 4.遍历结果并打印
System.out.println(cityName);
}
/**
* 1.queryForObject函数入参带查询条件
* 2.根据基本类型封装返回值
* 3.查询一条记录的一个字段值
*/
public static void f5_1_2() {
// 1.获取查询sql
String sql = getSelectSql06();
// 2.获取JdbcTemplate
JdbcTemplate jt = getJdbcTemplate();
// 3.组装查询条件
Object[] args = new Object[]{"杭州", "1"};
// 4.查询数据集
String cityName = jt.queryForObject(sql, String.class, args);
// 5.遍历结果并打印
System.out.println(cityName);
}
/**
* 1.queryForObject函数入参带查询条件,入参带参数类型
* 2.根据基本类型封装返回值
* 3.查询一条记录的一个字段值
*/
public static void f5_1_3() {
// 1.获取查询sql
String sql = getSelectSql06();
// 2.获取JdbcTemplate
JdbcTemplate jt = getJdbcTemplate();
// 3.组装查询条件
Object[] args = new Object[]{"杭州", "1"};
int[] argTypes = new int[]{Types.VARCHAR, Types.BIGINT};
// 4.查询数据集
String cityName = jt.queryForObject(sql, args, argTypes, String.class);
// 5.遍历结果并打印
System.out.println(cityName);
}
/**
* 1.select语句,查一条数据的一个字段
* 2.queryForObject函数入参带查询条件
*/
public static String getSelectSql05() {
String sql05 = "SELECT\n" +
" CITY_NAME\n" +
"FROM t_city limit 1";
return sql05.toString();
}
/**
* 1.select语句,查一条数据的一个字段
* 2.queryForObject函数入参带查询条件
*/
public static String getSelectSql06() {
String sql06 = "SELECT\n" +
" CITY_NAME \n" +
"FROM t_city " +
"WHERE CITY_NAME = ? AND ID =? limit 1";
return sql06.toString();
}
5.2 queryForObject查询一条记录
5.2.1 queryForObject函数定义
queryForObject的以下3个函数,查询一条记录。
参数sql:数据库执行的SQL语句。
参数rowMapper:是RowMapper接口实现类,把数据库返回的结果集表字段与值,封装成自定义的JavaBean对象。
参数args:是SQL中有占位符?时,传入变量的方式。
参数argTypes:是args传入参数对应的数据库表字段的数据类型。
public <T> T queryForObject(String sql, RowMapper<T> rowMapper);
public <T> T queryForObject(String sql, RowMapper<T> rowMapper, @Nullable Object... args);
public <T> T queryForObject(String sql, Object[] args, int[] argTypes, RowMapper<T> rowMapper);
5.2.2 queryForObject使用场景
场景:使用queryForObject函数,可以把查询结果集按照自定义的JavaBean封装,返回值为JavaBean。
5.2.3 queryForObject使用举例
/**
* 1.queryForObject函数入参不带查询条件,如有查询条件直接写在SQL中
* 2.使用自定义CityRowMapper封装返回值
* 3.查询一条记录,返回值即自定义对象
*/
public static void f5_2_1() {
// 1.获取查询sql
String sql = getSelectSql03();
// 2.获取JdbcTemplate
JdbcTemplate jt = getJdbcTemplate();
// 3.查询数据集
CityPO cityPO = jt.queryForObject(sql, new CityRowMapper());
// 4.遍历结果并打印
System.out.println(cityPO);
}
/**
* 1.queryForObject函数入参带查询条件
* 2.使用自定义CityRowMapper封装返回值
* 3.查询一条记录,返回值即自定义对象
*/
public static void f5_2_2() {
// 1.获取查询sql
String sql = getSelectSql04();
// 2.获取JdbcTemplate
JdbcTemplate jt = getJdbcTemplate();
// 3.组装查询条件
Object[] args = new Object[]{"杭州", "1"};
// 4.查询数据集
CityPO cityPO = jt.queryForObject(sql, new CityRowMapper(), args);
// 5.遍历结果并打印
System.out.println(cityPO);
}
/**
* 1.queryForObject函数入参带查询条件,入参带参数类型
* 2.使用自定义CityRowMapper封装返回值
* 3.查询一条记录,返回值即自定义对象
*/
public static void f5_2_3() {
// 1.获取查询sql
String sql = getSelectSql04();
// 2.获取JdbcTemplate
JdbcTemplate jt = getJdbcTemplate();
// 3.组装查询条件
Object[] args = new Object[]{"杭州", "1"};
int[] argTypes = new int[]{Types.VARCHAR, Types.BIGINT};
// 4.查询数据集
CityPO cityPO = jt.queryForObject(sql, args, argTypes, new CityRowMapper());
// 5.遍历结果并打印
System.out.println(cityPO);
}
/**
* 1.select语句,查一条数据
* 2.queryForMap函数入参不带查询条件
* 3.queryForObject函数入参不带查询条件
*/
public static String getSelectSql03() {
String sql01 = "SELECT\n" +
" ID,CITY_NAME,LAND_AREA,POPULATION,GROSS,\n" +
" CITY_DESCRIBE,DATA_YEAR,UPDATE_TIME\n" +
"FROM t_city limit 1";
return sql01.toString();
}
/**
* 1.select语句,查一条数据
* 2.queryForMap函数入参带查询条件
* 3.queryForObject函数入参带查询条件
*/
public static String getSelectSql04() {
String sql02 = "SELECT\n" +
" ID,CITY_NAME,LAND_AREA,POPULATION,GROSS,\n" +
" CITY_DESCRIBE,DATA_YEAR,UPDATE_TIME\n" +
"FROM t_city " +
"WHERE CITY_NAME = ? AND ID =? limit 1";
return sql02.toString();
}
6.queryForList函数
6.1 queryForList查询多条记录
6.1.1 queryForList函数定义
参数sql:数据库执行的SQL语句。
参数args:是SQL中有占位符?时,传入变量的方式。
参数argTypes:是args传入参数对应的数据库表字段的数据类型。
public List<Map<String, Object>> queryForList(String sql)
public List<Map<String, Object>> queryForList(String sql, @Nullable Object... args);
public List<Map<String, Object>> queryForList(String sql, Object[] args, int[] argTypes);
6.1.2 queryForList使用场景
场景:使用queryForList函数,把查询结果集封装为List<Map<String, Object>>,遍历List取出每条记录,即一条记录一个Map<String, Object>,一个Map对应数据库表中的字段和字段值,即Map的key,value键值对。
6.1.3 queryForList使用举例
/**
* 1.queryForList函数入参不带查询条件,如有查询条件直接写在SQL中
* 2.使用List<Map<String, Object>>封装返回值
* 3.使用java.util.stream.Stream遍历结果
*/
public static void f6_1_1() {
// 1.获取查询sql
String sql = getSelectSql01();
// 2.获取JdbcTemplate
JdbcTemplate jt = getJdbcTemplate();
// 3.查询数据集
List<Map<String, Object>> list = jt.queryForList(sql);
// 4.遍历结果并打印,使用Stream函数式遍历
Stream<Map<String, Object>> stream = list.stream();
System.out.println("遍历List.");
AtomicInteger i = new AtomicInteger(1);
stream.forEach(map -> {
System.out.println("遍历第 " + i + " 条记录.");
AtomicInteger j = new AtomicInteger(1);
map.forEach((key, value) -> {
System.out.println(key + " = " + value.toString());
});
i.getAndIncrement();
});
}
/**
* 1.queryForList函数入参带查询条件
* 2.使用List<Map<String, Object>>封装返回值
* 3.使用for循环和Map.Entry遍历结果
*/
public static void f6_1_2() {
// 1.获取查询sql
String sql = getSelectSql02();
// 2.获取JdbcTemplate
JdbcTemplate jt = getJdbcTemplate();
// 3.组装查询条件
Object[] args = new Object[]{"杭州", "1"};
// 4.查询数据集
List<Map<String, Object>> list = jt.queryForList(sql, args);
// 5.遍历结果并打印,使用for遍历
for (Map<String, Object> map : list) {
for (Map.Entry<String, Object> entry : map.entrySet()) {
System.out.println(entry.getKey() + " = " + entry.getValue());
}
}
}
/**
* 1.queryForList函数入参带查询条件,入参带参数类型
* 2.使用List<Map<String, Object>>封装返回值
* 3.使用for循环和while循环和Map.Entry遍历结果
*/
public static void f6_1_3() {
// 1.获取查询sql
String sql = getSelectSql02();
// 2.获取JdbcTemplate
JdbcTemplate jt = getJdbcTemplate();
// 3.组装查询条件
Object[] args = new Object[]{"杭州", "1"};
int[] argTypes = new int[]{Types.VARCHAR, Types.BIGINT};
// 4.查询数据集
List<Map<String, Object>> list = jt.queryForList(sql, args, argTypes);
// 5.遍历结果并打印,使用for遍历,和while遍历
for (int i = 0; i < list.size(); i++) {
Map<String, Object> map = list.get(i);
Iterator<Map.Entry<String, Object>> entries = map.entrySet().iterator();
while (entries.hasNext()) {
Map.Entry<String, Object> entry = entries.next();
System.out.println(entry.getKey() + " = " + entry.getValue());
}
}
}
/**
* 1.select语句
* 2.query函数入参不带查询条件
* 3.queryForStream函数入参不带查询条件
* 4.queryForRowSet函数入参不带查询条件
* 5.queryForList函数入参不带查询条件
*/
public static String getSelectSql01() {
String sql01 = "SELECT\n" +
" ID,CITY_NAME,LAND_AREA,POPULATION,GROSS,\n" +
" CITY_DESCRIBE,DATA_YEAR,UPDATE_TIME\n" +
"FROM t_city ";
return sql01.toString();
}
/**
* 1.select语句
* 2.query函数入参带查询条件
* 3.queryForStream函数入参带查询条件
* 4.queryForRowSet函数入参带查询条件
* 5.queryForList函数入参带查询条件
*/
public static String getSelectSql02() {
String sql02 = "SELECT\n" +
" ID,CITY_NAME,LAND_AREA,POPULATION,GROSS,\n" +
" CITY_DESCRIBE,DATA_YEAR,UPDATE_TIME\n" +
"FROM t_city " +
"WHERE CITY_NAME = ? AND ID =? ";
return sql02.toString();
}
6.2 queryForList查一个字段的多条记录
6.2.1 queryForList函数定义
参数sql:数据库执行的SQL语句。
参数elementType:封装返回值类型。
参数args:是SQL中有占位符?时,传入变量的方式。
参数argTypes:是args传入参数对应的数据库表字段的数据类型。
public <T> List<T> queryForList(String sql, Class<T> elementType);
public <T> List<T> queryForList(String sql, Class<T> elementType, @Nullable Object... args);
public <T> List<T> queryForList(String sql, Object[] args, int[] argTypes, Class<T> elementType);
6.2.2 queryForList使用场景
场景:使用queryForList函数,把查询结果封装为指定的基本类型,返回值封装在 List<T> 中。适合查询一个字段的多条记录。
6.2.3 queryForList使用举例
/**
* 1.queryForList函数入参不带查询条件,如有查询条件直接写在SQL中
* 2.查一个字段的多条记录,使用List<T>封装返回值
* 3.使用java.util.stream.Stream遍历结果
*/
public static void f6_2_1() {
// 1.获取查询sql
String sql = getSelectSql07();
// 2.获取JdbcTemplate
JdbcTemplate jt = getJdbcTemplate();
// 3.查询数据集
List<String> list = jt.queryForList(sql, String.class);
// 4.遍历结果并打印
Stream<String> stream = list.stream();
stream.forEach(cityName -> {
System.out.println(cityName.toString());
});
}
/**
* 1.queryForList函数入参带查询条件
* 2.查一个字段的多条记录,使用List<T>封装返回值
* 3.使用java.util.stream.Stream遍历结果
*/
public static void f6_2_2() {
// 1.获取查询sql
String sql = getSelectSql08();
// 2.获取JdbcTemplate
JdbcTemplate jt = getJdbcTemplate();
// 3.组装查询条件
Object[] args = new Object[]{"杭州", "1"};
// 4.查询数据集
List<String> list = jt.queryForList(sql, String.class, args);
// 5.遍历结果并打印
Stream<String> stream = list.stream();
stream.forEach(cityName -> {
System.out.println(cityName.toString());
});
}
/**
* 1.queryForList函数入参带查询条件,入参带参数类型
* 2.查一个字段的多条记录,使用List<T>封装返回值
* 3.使用java.util.stream.Stream遍历结果
*/
public static void f6_2_3() {
// 1.获取查询sql
String sql = getSelectSql08();
// 2.获取JdbcTemplate
JdbcTemplate jt = getJdbcTemplate();
// 3.组装查询条件
Object[] args = new Object[]{"杭州", "1"};
int[] argTypes = new int[]{Types.VARCHAR, Types.BIGINT};
// 4.查询数据集
List<String> list = jt.queryForList(sql, args, argTypes, String.class);
// 5.遍历结果并打印
Stream<String> stream = list.stream();
stream.forEach(cityName -> {
System.out.println(cityName.toString());
});
}
/**
* 1.select语句,一个字段的多条记录
* 2.queryForList函数入参不带查询条件
*/
public static String getSelectSql07() {
String sql07 = "SELECT\n" +
" CITY_NAME\n" +
"FROM t_city ";
return sql07.toString();
}
/**
* 1.select语句,一个字段的多条记录
* 2.queryForList函数入参带查询条件
*/
public static String getSelectSql08() {
String sql08 = "SELECT\n" +
" CITY_NAME\n" +
"FROM t_city " +
"WHERE CITY_NAME = ? AND ID =? ";
return sql08.toString();
}
7.查询函数共用代码
7.1 获取JdbcTemplate实例对象
封装统一方法获取JdbcTemplate,使用时替换为实际数据库连接信息。
/**
* 获取一个JdbcTemplate实例对象
*/
public static JdbcTemplate getJdbcTemplate() {
String username = "***自定义填写**";
String password = "***自定义填写**";
String jdbcUrl = "jdbc:mysql://127.0.0.1:3306/***自定义填写**";
String driverName = "com.mysql.cj.jdbc.Driver";
DruidDataSource dataSource = new DruidDataSource();
dataSource.setPassword(password);
dataSource.setUrl(jdbcUrl);
dataSource.setUsername(username);
dataSource.setDriverClassName(driverName);
JdbcTemplate jdbcTemplate = new JdbcTemplate();
jdbcTemplate.setDataSource(dataSource);
return jdbcTemplate;
}
7.2 实现RowMapper接口对象
本例CityRowMapper实现RowMapper接口,封装结果集和JavaBean对应关系。
/**
* 实现JdbcTemplate的RowMapper接口
* 数据库查询的字段和自定义JavaBean属性匹配
*/
private static class CityRowMapper implements RowMapper<CityPO> {
@Override
public CityPO mapRow(ResultSet rs, int rowNum) throws SQLException {
CityPO cityPO = new CityPO();
cityPO.setId((Long) rs.getObject("ID"));
cityPO.setCityName((String) rs.getObject("CITY_NAME"));
cityPO.setLandArea((Double) rs.getObject("LAND_AREA"));
cityPO.setPopulation((Long) rs.getObject("POPULATION"));
cityPO.setGross((Double) rs.getObject("GROSS"));
cityPO.setCityDescribe((String) rs.getObject("CITY_DESCRIBE"));
cityPO.setDataYear((String) rs.getObject("DATA_YEAR"));
cityPO.setUpdateTime((LocalDateTime) rs.getObject("UPDATE_TIME"));
return cityPO;
}
}
7.3 JavaBean对象
JavaBean对象与数据库表字段一一对应,以驼峰法命名。
@Data
@NoArgsConstructor
public class CityPO {
private long id;
private String cityName;
private double landArea;
private long population;
private double gross;
private String cityDescribe;
private String dataYear;
private LocalDateTime updateTime;
二、增
增,即使用JdbcTemplate对数据库的数据做插入操作。
SQL关键字:insert into。
1.update函数
1.1 update函数定义
执行数据数据库insert into插入数据,使用update函数实现。
参数sql:数据库执行的SQL语句。
参数pss:对应入参和占位符字段匹配关系。
参数args:是SQL中有占位符?时,传入变量的方式。
参数argTypes:是args传入参数对应的数据库表字段的数据类型。
public int update(final String sql);
public int update(String sql, @Nullable Object... args);
public int update(String sql, @Nullable PreparedStatementSetter pss);
public int update(String sql, Object[] args, int[] argTypes);
1.2 update使用场景
场景:使用update函数,可以执行数据库的insert into插入数据。
1.3 update使用举例
/**
* 1.insert插入语句,使用update函数
* 2.update函数入参不带插入数据,数据直接写在insert into语句中
*/
public static void f7_1() {
// 1.获取插入sql
String sql = getInsertSql02();
// 2.获取JdbcTemplate
JdbcTemplate jt = getJdbcTemplate();
// 3.执行insert into语句
int result = jt.update(sql);
// 4.打印返回值
System.out.println("插入返回值: " + result);
}
/**
* 1.insert插入语句,使用update函数
* 2.update函数入参带插入数据
*/
public static void f7_2() {
// 1.获取插入sql
String sql = getInsertSql01();
// 2.获取JdbcTemplate
JdbcTemplate jt = getJdbcTemplate();
// 3.组装插入参数
Object[] args = new Object[]{
"杭州", "16850", "1200", "1.61",
"杭州是一个好城市", "2020", "2022-07-23 16:39:16"
};
// 4.执行insert into语句
int result = jt.update(sql, args);
// 5.打印返回值
System.out.println("插入返回值: " + result);
}
/**
* 1.insert插入语句,使用update函数
* 2.update函数入参带插入数据
* 3.使用PreparedStatementSetter对应入参和字段关系
*/
public static void f7_3() {
// 1.获取插入sql
String sql = getInsertSql01();
// 2.获取JdbcTemplate
JdbcTemplate jt = getJdbcTemplate();
// 3.组装插入参数
Object[] args = new Object[]{
"杭州", "16850", "1200", "1.61",
"杭州是一个好城市", "2020", "2022-07-23 16:39:18"
};
// 4.执行insert语句(插入一条数据)
int result = jt.update(sql, new PreparedStatementSetter() {
@Override
public void setValues(PreparedStatement ps) throws SQLException {
ps.setObject(1, args[0]);
ps.setObject(2, args[1]);
ps.setObject(3, args[2]);
ps.setObject(4, args[3]);
ps.setObject(5, args[4]);
ps.setObject(6, args[5]);
ps.setObject(7, args[6]);
}
});
// 5.打印返回值
System.out.println("插入返回值: " + result);
}
/**
* 1.insert插入语句,使用update函数
* 2.update函数入参带插入数据,入参带参数类型
*/
public static void f7_4() {
// 1.获取插入sql
String sql = getInsertSql01();
// 2.获取JdbcTemplate
JdbcTemplate jt = getJdbcTemplate();
// 3.组装插入参数
Object[] args = new Object[]{
"杭州", "16850", "1200", "1.61",
"杭州是一个好城市", "2020", "2022-07-23 16:39:19"
};
int[] argTypes = new int[]{Types.VARCHAR,
Types.DOUBLE, Types.BIGINT, Types.DOUBLE,
Types.VARCHAR, Types.VARCHAR, Types.TIMESTAMP
};
// 4.执行insert语句
int result = jt.update(sql, args, argTypes);
// 5.打印返回值
System.out.println("插入返回值: " + result);
}
/**
* 1.insert语句,插入数据
* 2.update函数入参带插入数据
*/
public static String getInsertSql01() {
String sql01 = "INSERT INTO t_city (\n" +
" CITY_NAME,LAND_AREA,POPULATION,\n" +
" GROSS,CITY_DESCRIBE,DATA_YEAR,UPDATE_TIME\n" +
")\n" +
"VALUES (?, ?, ?, ?, ?, ?, ?)";
return sql01.toString();
}
/**
* 1.insert语句,插入数据
* 2.update函数入参不带插入数据
*/
public static String getInsertSql02() {
String sql02 = "INSERT INTO t_city (\n" +
" CITY_NAME,LAND_AREA,POPULATION,\n" +
" GROSS,CITY_DESCRIBE,DATA_YEAR,UPDATE_TIME)\n" +
" VALUES('杭州','16850','1200','1.61',\n" +
" '杭州是一个好城市','2020','2022-07-23 16:39:16')";
return sql02.toString();
}
2.batchUpdate函数
2.1 batchUpdate函数定义
执行数据数据库insert into批量插入数据,使用batchUpdate函数实现。
参数sql:数据库执行的SQL语句。
参数pss:对应入参和占位符字段匹配关系。
参数batchArgs:是SQL中有占位符?时,传入变量的方式。
参数argTypes:是args传入参数对应的数据库表字段的数据类型。
参数batchSize:入参大小,即batchArgs条数。
public int[] batchUpdate(final String... sql);
public int[] batchUpdate(String sql, List<Object[]> batchArgs);
public int[] batchUpdate(String sql, List<Object[]> batchArgs, final int[] argTypes);
public int[] batchUpdate(String sql, final BatchPreparedStatementSetter pss);
public <T> int[][] batchUpdate(String sql, final Collection<T> batchArgs, final int batchSize, final ParameterizedPreparedStatementSetter<T> pss);
2.2 batchUpdate使用场景
场景:使用batchUpdate函数,可以执行数据库的insert into批量插入数据。
2.3 batchUpdate使用举例
/**
* 1.insert插入语句,使用batchUpdate函数
* 2.batchUpdate函数入参不带插入数据,数据直接写在insert into语句中
*/
public static void f8_1() {
// 1.获取插入sql
String[] sql = getInsertSql03();
// 2.获取JdbcTemplate
JdbcTemplate jt = getJdbcTemplate();
// 3.执行insert语句
int[] result = jt.batchUpdate(sql);
// 4.遍历并打印返回值
List<Integer> list = Arrays.stream(result).boxed().collect(Collectors.toList());
for (Object var : list) {
System.out.println("返回值: " + var);
}
}
/**
* 1.insert插入语句,使用batchUpdate函数
* 2.batchUpdate函数入参带插入数据
*/
public static void f8_2() {
// 1.获取插入sql
String sql = getInsertSql01();
// 2.获取JdbcTemplate
JdbcTemplate jt = getJdbcTemplate();
// 3.组装插入参数
List<Object[]> batchArgs = getInsertBatchArgs();
// 4.执行insert语句
int[] result = jt.batchUpdate(sql, batchArgs);
// 5.打印返回值
List<Integer> list = Arrays.stream(result).boxed().collect(Collectors.toList());
for (Object var : list) {
System.out.println("返回值: " + var);
}
}
/**
* 1.insert插入语句,使用batchUpdate函数
* 2.batchUpdate函数入参带插入数据,入参带参数类型
*/
public static void f8_3() {
// 1.获取插入sql
String sql = getInsertSql01();
// 2.获取JdbcTemplate
JdbcTemplate jt = getJdbcTemplate();
// 3.组装插入参数
List<Object[]> batchArgs = getInsertBatchArgs();
int[] argTypes = new int[]{Types.VARCHAR,
Types.DOUBLE, Types.BIGINT, Types.DOUBLE,
Types.VARCHAR, Types.VARCHAR, Types.TIMESTAMP
};
// 4.执行insert语句
int[] result = jt.batchUpdate(sql, batchArgs, argTypes);
// 5.打印返回值
List<Integer> list = Arrays.stream(result).boxed().collect(Collectors.toList());
for (Object var : list) {
System.out.println("返回值: " + var);
}
}
/**
* 1.insert插入语句,使用batchUpdate函数
* 2.batchUpdate函数入参带插入数据
* 3.使用BatchPreparedStatementSetter对应入参和字段关系
*/
public static void f8_4() {
// 1.获取插入sql
String sql = getInsertSql01();
// 2.获取JdbcTemplate
JdbcTemplate jt = getJdbcTemplate();
// 3.组装插入参数
List<Object[]> batchArgs = getInsertBatchArgs();
// 4.执行insert语句
int[] result = jt.batchUpdate(sql, new BatchPreparedStatementSetter() {
@Override
public void setValues(PreparedStatement ps, int i) throws SQLException {
// 第一行开始
Object[] args = batchArgs.get(i);
ps.setObject(1, args[0]);
ps.setObject(2, args[1]);
ps.setObject(3, args[2]);
ps.setObject(4, args[3]);
ps.setObject(5, args[4]);
ps.setObject(6, args[5]);
ps.setObject(7, args[6]);
}
@Override
public int getBatchSize() {
return batchArgs.size();
}
});
// 5.打印返回值
List<Integer> list = Arrays.stream(result).boxed().collect(Collectors.toList());
for (Object var : list) {
System.out.println("返回值: " + var);
}
}
/**
* 1.insert插入语句,使用batchUpdate函数
* 2.batchUpdate函数入参带插入数据
* 3.使用ParameterizedPreparedStatementSetter对应入参和字段关系
*/
public static void f8_5() {
// 1.获取插入sql
String sql = getInsertSql01();
// 2.获取JdbcTemplate
JdbcTemplate jt = getJdbcTemplate();
// 3.组装插入参数
List<Object[]> batchArgs = getInsertBatchArgs();
// 4.执行insert语句
int[][] result = jt.batchUpdate(sql, batchArgs, batchArgs.size(),
new ParameterizedPreparedStatementSetter() {
@Override
public void setValues(PreparedStatement ps, Object argument) throws SQLException {
Object[] args = (Object[]) argument;
ps.setObject(1, args[0]);
ps.setObject(2, args[1]);
ps.setObject(3, args[2]);
ps.setObject(4, args[3]);
ps.setObject(5, args[4]);
ps.setObject(6, args[5]);
ps.setObject(7, args[6]);
}
});
// 5.打印返回值
for (int[] ints : result) {
for (int anInt : ints) {
System.out.println("返回值: " + anInt);
}
}
}
/**
* 1.insert语句,插入数据
* 2.update函数入参带插入数据
*/
public static String getInsertSql01() {
String sql01 = "INSERT INTO t_city (\n" +
" CITY_NAME,LAND_AREA,POPULATION,\n" +
" GROSS,CITY_DESCRIBE,DATA_YEAR,UPDATE_TIME\n" +
")\n" +
"VALUES (?, ?, ?, ?, ?, ?, ?)";
return sql01.toString();
}
/**
* 1.insert语句,插入数据
* 2.update函数入参不带插入数据
*/
public static String[] getInsertSql03() {
String sql01 = "INSERT INTO t_city (\n" +
" CITY_NAME,LAND_AREA,POPULATION,\n" +
" GROSS,CITY_DESCRIBE,DATA_YEAR,UPDATE_TIME)\n" +
" VALUES('杭州','16850','1200','1.61',\n" +
" '杭州是一个好城市','2020','2022-07-23 16:39:16')";
String sql02 = "INSERT INTO t_city (\n" +
" CITY_NAME,LAND_AREA,POPULATION,\n" +
" GROSS,CITY_DESCRIBE,DATA_YEAR,UPDATE_TIME)\n" +
" VALUES('杭州','16850','1200','1.81',\n" +
" '杭州是一个好城市','2021','2022-07-23 16:39:19')";
return new String[]{sql01, sql02};
}
/**
* 1.执行数据库insert into语句
* 2.获取批量插入数据
*/
public static List<Object[]> getInsertBatchArgs() {
Object[] args1 = new Object[]{
"杭州", "16850", "1200", "1.61",
"杭州是一个好城市", "2020", "2022-07-23 16:39:51"
};
Object[] args2 = new Object[]{
"杭州", "16850", "1200", "1.81",
"杭州是一个好城市", "2021", "2022-07-23 16:39:52"
};
List<Object[]> batchArgs = new ArrayList<>();
batchArgs.add(args1);
batchArgs.add(args2);
return batchArgs;
}
三、改
改,即使用JdbcTemplate对数据库的数据做修改操作。
SQL关键字:update。
1.update函数
1.1 update函数定义
执行数据数据库update修改数据,使用update函数实现。
参数sql:数据库执行的SQL语句。
参数pss:对应入参和占位符字段匹配关系。
参数args:是SQL中有占位符?时,传入变量的方式。
参数argTypes:是args传入参数对应的数据库表字段的数据类型。
public int update(final String sql);
public int update(String sql, @Nullable Object... args);
public int update(String sql, @Nullable PreparedStatementSetter pss);
public int update(String sql, Object[] args, int[] argTypes);
1.2 update使用场景
场景:使用update函数,可以执行数据库的update需改数据。
1.3 update使用举例
/**
* 1.update修改数据语句,使用update函数
* 2.update函数入参不带修改数据,数据直接写在update语句中
*/
public static void f9_1() {
// 1.获取修改sql
String sql = getUpdateSql01();
// 2.获取JdbcTemplate
JdbcTemplate jt = getJdbcTemplate();
// 3.执行update语句
int result = jt.update(sql);
// 4.遍历并打印返回值
System.out.println("返回值: " + result);
}
/**
* 1.update修改数据语句,使用update函数
* 2.update函数入参带修改数据
*/
public static void f9_2() {
// 1.获取修改sql
String sql = getUpdateSql02();
// 2.获取JdbcTemplate
JdbcTemplate jt = getJdbcTemplate();
// 3.组装修改参数
Object[] args = new Object[]{"杭州是互联网城市", "2022-07-23 17:39:51", "杭州", "1"};
// 4.执行update语句
int result = jt.update(sql, args);
// 5.打印返回值
System.out.println("插入返回值: " + result);
}
/**
* 1.update修改数据语句,使用update函数
* 2.update函数入参带修改数据
* 3.使用PreparedStatementSetter对应入参和字段关系
*/
public static void f9_3() {
// 1.获取修改sql
String sql = getUpdateSql02();
// 2.获取JdbcTemplate
JdbcTemplate jt = getJdbcTemplate();
// 3.组装修改参数
Object[] args = new Object[]{"杭州是互联网城市", "2022-07-23 16:39:22", "杭州", "1"};
// 4.执行update语句
int result = jt.update(sql, new PreparedStatementSetter() {
@Override
public void setValues(PreparedStatement ps) throws SQLException {
ps.setObject(1, args[0]);
ps.setObject(2, args[1]);
ps.setObject(3, args[2]);
ps.setObject(4, args[3]);
}
});
// 5.打印返回值
System.out.println("插入返回值: " + result);
}
/**
* 1.update修改数据语句,使用update函数
* 2.update函数入参带修改数据,入参带参数类型
*/
public static void f9_4() {
// 1.获取修改sql
String sql = getUpdateSql02();
// 2.获取JdbcTemplate
JdbcTemplate jt = getJdbcTemplate();
// 3.组装修改参数
Object[] args = new Object[]{"杭州是互联网城市", "2022-07-23 16:39:35", "杭州", "1"};
int[] argTypes = new int[]{Types.VARCHAR, Types.TIMESTAMP,
Types.VARCHAR, Types.BIGINT
};
// 4.执行update语句
int result = jt.update(sql, args, argTypes);
// 5.打印返回值
System.out.println("插入返回值: " + result);
}
/**
* 1.update语句修改数据
* 2.update函数入参不带修改数据
*/
public static String getUpdateSql01() {
String sql = "UPDATE t_city\n" +
"SET CITY_DESCRIBE = '杭州是互联网城市'\n" +
"WHERE CITY_NAME = '杭州' AND ID = '1' ";
return sql.toString();
}
/**
* 1.update语句,修改数据
* 2.使用update函数入参带修改数据
* 3.使用batchUpdate函数入参带修改数据
*/
public static String getUpdateSql02() {
String sql = "UPDATE t_city\n" +
"SET CITY_DESCRIBE = ?,UPDATE_TIME = ?\n" +
"WHERE CITY_NAME = ? AND ID = ? ";
return sql.toString();
}
2.batchUpdate函数
2.1 batchUpdate函数定义
执行数据数据库update批量修改数据,使用batchUpdate函数实现。
参数sql:数据库执行的SQL语句。
参数pss:对应入参和占位符字段匹配关系。
参数batchArgs:是SQL中有占位符?时,传入变量的方式。
参数argTypes:是args传入参数对应的数据库表字段的数据类型。
参数batchSize:入参大小,即batchArgs条数。
public int[] batchUpdate(final String... sql);
public int[] batchUpdate(String sql, List<Object[]> batchArgs);
public int[] batchUpdate(String sql, List<Object[]> batchArgs, final int[] argTypes);
public int[] batchUpdate(String sql, final BatchPreparedStatementSetter pss);
public <T> int[][] batchUpdate(String sql, final Collection<T> batchArgs, final int batchSize, final ParameterizedPreparedStatementSetter<T> pss);
2.2 batchUpdate使用场景
场景:使用batchUpdate函数,可以执行数据库的update批量修改数据。
2.3 batchUpdate使用举例
/**
* 1.update修改数据语句,使用batchUpdate函数
* 2.batchUpdate函数入参不带修改数据,数据直接写在update语句中
*/
public static void f10_1() {
// 1.获取修改sql
String[] sql = getUpdateSql03();
// 2.获取JdbcTemplate
JdbcTemplate jt = getJdbcTemplate();
// 3.执行update语句
int[] result = jt.batchUpdate(sql);
// 4.遍历并打印返回值
List<Integer> list = Arrays.stream(result).boxed().collect(Collectors.toList());
for (Object var : list) {
System.out.println("返回值: " + var);
}
}
/**
* 1.update修改数据语句,使用batchUpdate函数
* 2.batchUpdate函数入参带修改数据
*/
public static void f10_2() {
// 1.获取修改sql
String sql = getUpdateSql02();
// 2.获取JdbcTemplate
JdbcTemplate jt = getJdbcTemplate();
// 3.组装修改参数
List<Object[]> batchArgs = getUpdateBatchArgs();
// 4.执行update语句
int[] result = jt.batchUpdate(sql, batchArgs);
// 5.打印返回值
List<Integer> list = Arrays.stream(result).boxed().collect(Collectors.toList());
for (Object var : list) {
System.out.println("返回值: " + var);
}
}
/**
* 1.update修改数据语句,使用batchUpdate函数
* 2.batchUpdate函数入参带修改数据,入参带参数类型
*/
public static void f10_3() {
// 1.获取修改sql
String sql = getUpdateSql02();
// 2.获取JdbcTemplate
JdbcTemplate jt = getJdbcTemplate();
// 3.组装修改参数
List<Object[]> batchArgs = getUpdateBatchArgs();
int[] argTypes = new int[]{Types.VARCHAR, Types.TIMESTAMP,
Types.VARCHAR, Types.BIGINT
};
// 4.执行update语句
int[] result = jt.batchUpdate(sql, batchArgs, argTypes);
// 5.打印返回值
List<Integer> list = Arrays.stream(result).boxed().collect(Collectors.toList());
for (Object var : list) {
System.out.println("返回值: " + var);
}
}
/**
* 1.update修改数据语句,使用batchUpdate函数
* 2.batchUpdate函数入参带修改数据
* 3.使用BatchPreparedStatementSetter对应入参和字段关系
*/
public static void f10_4() {
// 1.获取修改sql
String sql = getUpdateSql02();
// 2.获取JdbcTemplate
JdbcTemplate jt = getJdbcTemplate();
// 3.组装修改参数
List<Object[]> batchArgs = getUpdateBatchArgs();
// 4.执行update语句
int[] result = jt.batchUpdate(sql, new BatchPreparedStatementSetter() {
@Override
public void setValues(PreparedStatement ps, int i) throws SQLException {
// 第一行开始
Object[] args = batchArgs.get(i);
ps.setObject(1, args[0]);
ps.setObject(2, args[1]);
ps.setObject(3, args[2]);
ps.setObject(4, args[3]);
}
@Override
public int getBatchSize() {
return batchArgs.size();
}
});
// 5.打印返回值
List<Integer> list = Arrays.stream(result).boxed().collect(Collectors.toList());
for (Object var : list) {
System.out.println("返回值: " + var);
}
}
/**
* 1.update修改数据语句,使用batchUpdate函数
* 2.batchUpdate函数入参带修改数据
* 3.使用ParameterizedPreparedStatementSetter对应入参和字段关系
*/
public static void f10_5() {
// 1.获取修改sql
String sql = getUpdateSql02();
// 2.获取JdbcTemplate
JdbcTemplate jt = getJdbcTemplate();
// 3.组装修改参数
List<Object[]> batchArgs = getUpdateBatchArgs();
// 4.执行update语句
int[][] result = jt.batchUpdate(sql, batchArgs, batchArgs.size(),
new ParameterizedPreparedStatementSetter() {
@Override
public void setValues(PreparedStatement ps, Object argument) throws SQLException {
Object[] args = (Object[]) argument;
ps.setObject(1, args[0]);
ps.setObject(2, args[1]);
ps.setObject(3, args[2]);
ps.setObject(4, args[3]);
}
});
// 5.打印返回值
for (int[] ints : result) {
for (int anInt : ints) {
System.out.println("返回值: " + anInt);
}
}
}
/**
* 1.update语句,修改数据
* 2.使用update函数入参带修改数据
* 3.使用batchUpdate函数入参带修改数据
*/
public static String getUpdateSql02() {
String sql = "UPDATE t_city\n" +
"SET CITY_DESCRIBE = ?,UPDATE_TIME = ?\n" +
"WHERE CITY_NAME = ? AND ID = ? ";
return sql.toString();
}
/**
* 1.update语句修改数据
* 2.使用batchUpdate函数入参不带修改数据
*/
public static String[] getUpdateSql03() {
String sql01 = "UPDATE t_city\n" +
"SET CITY_DESCRIBE = '杭州是互联网城市01'\n" +
"WHERE CITY_NAME = '杭州' AND ID = '1' ";
String sql02 = "UPDATE t_city\n" +
"SET CITY_DESCRIBE = '杭州是互联网城市02'\n" +
"WHERE CITY_NAME = '杭州' AND ID = '2' ";
return new String[]{sql01, sql02};
}
/**
* 1.执行数据库update语句
* 2.获取批量修改数据
*/
public static List<Object[]> getUpdateBatchArgs() {
Object[] args1 = new Object[]{"杭州是互联网城市01", "2022-07-23 16:39:57", "杭州", "1"};
Object[] args2 = new Object[]{"杭州是互联网城市02", "2022-07-23 16:39:58", "杭州", "2"};
List<Object[]> batchArgs = new ArrayList<>();
batchArgs.add(args1);
batchArgs.add(args2);
return batchArgs;
}
四、删
删,即使用JdbcTemplate对数据库的数据做删除操作。
SQL关键字:delete。
1.update函数
1.1 update函数定义
执行数据数据库delete删除数据,使用update函数实现。
参数sql:数据库执行的SQL语句。
参数pss:对应入参和占位符字段匹配关系。
参数args:是SQL中有占位符?时,传入变量的方式。
参数argTypes:是args传入参数对应的数据库表字段的数据类型。
public int update(final String sql);
public int update(String sql, @Nullable Object... args);
public int update(String sql, @Nullable PreparedStatementSetter pss);
public int update(String sql, Object[] args, int[] argTypes);
1.2 update使用场景
场景:使用update函数,可以执行数据库的delete删除数据。
1.3 update使用举例
/**
* 1.delete删除语句,使用update函数
* 2.update函数入参不带删除数据,数据直接写在delete语句中
*/
public static void f11_1() {
// 1.获取删除sql
String sql = getDeleteSql01();
// 2.获取JdbcTemplate
JdbcTemplate jt = getJdbcTemplate();
// 3.执行delete语句
int result = jt.update(sql);
// 4.遍历并打印返回值
System.out.println("返回值: " + result);
}
/**
* 1.delete删除语句,使用update函数
* 2.update函数入参带删除数据
*/
public static void f11_2() {
// 1.获取删除sql
String sql = getDeleteSql02();
// 2.获取JdbcTemplate
JdbcTemplate jt = getJdbcTemplate();
// 3.组装删除条件参数
Object[] args = new Object[]{"杭州", "1"};
// 4.执行delete语句
int result = jt.update(sql, args);
// 5.打印返回值
System.out.println("插入返回值: " + result);
}
/**
* 1.delete删除语句,使用update函数
* 2.update函数入参带删除数据
* 3.使用PreparedStatementSetter对应入参和字段关系
*/
public static void f11_3() {
// 1.获取删除sql
String sql = getDeleteSql02();
// 2.获取JdbcTemplate
JdbcTemplate jt = getJdbcTemplate();
// 3.组装删除条件参数
Object[] args = new Object[]{"杭州", "1"};
// 4.执行delete语句
int result = jt.update(sql, new PreparedStatementSetter() {
@Override
public void setValues(PreparedStatement ps) throws SQLException {
ps.setObject(1, args[0]);
ps.setObject(2, args[1]);
}
});
// 5.打印返回值
System.out.println("插入返回值: " + result);
}
/**
* 1.delete删除语句,使用update函数
* 2.update函数入参带删除数据,入参带参数类型
*/
public static void f11_4() {
// 1.获取删除sql
String sql = getDeleteSql02();
// 2.获取JdbcTemplate
JdbcTemplate jt = getJdbcTemplate();
// 3.组装删除条件参数
Object[] args = new Object[]{"杭州", "1"};
int[] argTypes = new int[]{Types.VARCHAR, Types.BIGINT};
// 4.执行delete语句
int result = jt.update(sql, args, argTypes);
// 5.打印返回值
System.out.println("插入返回值: " + result);
}
/**
* 1.delete语句,删除数据
* 2.使用update函数
*/
public static String getDeleteSql01() {
String sql = "DELETE FROM t_city WHERE CITY_NAME = '杭州' AND ID = '1' ";
return sql.toString();
}
/**
* 1.delete语句,删除数据
* 2.使用update函数
*/
public static String getDeleteSql02() {
String sql = "DELETE FROM t_city WHERE CITY_NAME = ? AND ID = ?";
return sql.toString();
}
2.batchUpdate函数
2.1 batchUpdate函数定义
执行数据数据库delete批量删除数据,使用batchUpdate函数实现。
参数sql:数据库执行的SQL语句。
参数pss:对应入参和占位符字段匹配关系。
参数batchArgs:是SQL中有占位符?时,传入变量的方式。
参数argTypes:是args传入参数对应的数据库表字段的数据类型。
参数batchSize:入参大小,即batchArgs条数。
public int[] batchUpdate(final String... sql);
public int[] batchUpdate(String sql, List<Object[]> batchArgs);
public int[] batchUpdate(String sql, List<Object[]> batchArgs, final int[] argTypes);
public int[] batchUpdate(String sql, final BatchPreparedStatementSetter pss);
public <T> int[][] batchUpdate(String sql, final Collection<T> batchArgs, final int batchSize, final ParameterizedPreparedStatementSetter<T> pss);
2.2 batchUpdate使用场景
场景:使用batchUpdate函数,可以执行数据库的delete批量删除数据。
2.3 batchUpdate使用举例
/**
* 1.delete删除语句,使用batchUpdate函数
* 2.batchUpdate函数入参不带删除数据,数据直接写在delete语句中
*/
public static void f12_1() {
// 1.获取删除sql
String[] sql = getDeleteSql03();
// 2.获取JdbcTemplate
JdbcTemplate jt = getJdbcTemplate();
// 3.执行delete语句
int[] result = jt.batchUpdate(sql);
// 4.遍历并打印返回值
List<Integer> list = Arrays.stream(result).boxed().collect(Collectors.toList());
for (Object var : list) {
System.out.println("返回值: " + var);
}
}
/**
* 1.delete删除语句,使用batchUpdate函数
* 2.batchUpdate函数入参带删除数据
*/
public static void f12_2() {
// 1.获取删除sql
String sql = getDeleteSql02();
// 2.获取JdbcTemplate
JdbcTemplate jt = getJdbcTemplate();
// 3.组装删除条件参数
List<Object[]> batchArgs = getDeleteBatchArgs();
// 4.执行delete语句
int[] result = jt.batchUpdate(sql, batchArgs);
// 5.打印返回值
List<Integer> list = Arrays.stream(result).boxed().collect(Collectors.toList());
for (Object var : list) {
System.out.println("返回值: " + var);
}
}
/**
* 1.delete删除语句,使用batchUpdate函数
* 2.batchUpdate函数入参带删除数据,入参带参数类型
*/
public static void f12_3() {
// 1.获取删除sql
String sql = getDeleteSql02();
// 2.获取JdbcTemplate
JdbcTemplate jt = getJdbcTemplate();
// 3.组装删除条件参数
List<Object[]> batchArgs = getDeleteBatchArgs();
int[] argTypes = new int[]{Types.VARCHAR, Types.BIGINT};
// 4.执行delete语句
int[] result = jt.batchUpdate(sql, batchArgs, argTypes);
// 5.打印返回值
List<Integer> list = Arrays.stream(result).boxed().collect(Collectors.toList());
for (Object var : list) {
System.out.println("返回值: " + var);
}
}
/**
* 1.delete删除语句,使用batchUpdate函数
* 2.batchUpdate函数入参带删除数据
* 3.使用BatchPreparedStatementSetter对应入参和字段关系
*/
public static void f12_4() {
// 1.获取删除sql
String sql = getDeleteSql02();
// 2.获取JdbcTemplate
JdbcTemplate jt = getJdbcTemplate();
// 3.组装删除条件参数
List<Object[]> batchArgs = getDeleteBatchArgs();
// 4.执行delete语句
int[] result = jt.batchUpdate(sql, new BatchPreparedStatementSetter() {
@Override
public void setValues(PreparedStatement ps, int i) throws SQLException {
// 第一行开始
Object[] args = batchArgs.get(i);
ps.setObject(1, args[0]);
ps.setObject(2, args[1]);
}
@Override
public int getBatchSize() {
return batchArgs.size();
}
});
// 5.打印返回值
List<Integer> list = Arrays.stream(result).boxed().collect(Collectors.toList());
for (Object var : list) {
System.out.println("返回值: " + var);
}
}
/**
* 1.delete删除语句,使用batchUpdate函数
* 2.batchUpdate函数入参带删除数据
* 3.使用ParameterizedPreparedStatementSetter对应入参和字段关系
*/
public static void f12_5() {
// 1.获取删除sql
String sql = getDeleteSql02();
// 2.获取JdbcTemplate
JdbcTemplate jt = getJdbcTemplate();
// 3.组装删除条件参数
List<Object[]> batchArgs = getDeleteBatchArgs();
// 4.执行delete语句
int[][] result = jt.batchUpdate(sql, batchArgs, batchArgs.size(),
new ParameterizedPreparedStatementSetter() {
@Override
public void setValues(PreparedStatement ps, Object argument) throws SQLException {
Object[] args = (Object[]) argument;
ps.setObject(1, args[0]);
ps.setObject(2, args[1]);
}
});
// 5.打印返回值
for (int[] ints : result) {
for (int anInt : ints) {
System.out.println("返回值: " + anInt);
}
}
}
/**
* 1.delete语句,删除数据
* 2.使用update函数
*/
public static String getDeleteSql02() {
String sql = "DELETE FROM t_city WHERE CITY_NAME = ? AND ID = ?";
return sql.toString();
}
/**
* 1.delete语句,删除数据
* 2.使用batchUpdate函数
*/
public static String[] getDeleteSql03() {
String sql01 = "DELETE FROM t_city WHERE CITY_NAME = '杭州' AND ID = '1' ";
String sql02 = "DELETE FROM t_city WHERE CITY_NAME = '杭州' AND ID = '2' ";
return new String[]{sql01, sql02};
}
/**
* 1.delete语句
* 2.获取批量删除参数
*/
public static List<Object[]> getDeleteBatchArgs() {
Object[] args1 = new Object[]{"杭州", "1"};
Object[] args2 = new Object[]{"杭州", "2"};
List<Object[]> batchArgs = new ArrayList<>();
batchArgs.add(args1);
batchArgs.add(args2);
return batchArgs;
}
五、支撑
针对本例使用JdbcTemplate对数据库的数据做查增改删操作,使用到的建表语句和数据初始化语句。
1.建表语句
建表语句,主键使用了MySQL的自增功能,即插入一条数据,可以不用赋值,但是赋值的话需判断不重复即可。
CREATE TABLE t_city (
ID BIGINT(16) NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT '主键',
CITY_NAME VARCHAR(64) COLLATE utf8_bin NOT NULL COMMENT '城市名',
LAND_AREA DOUBLE DEFAULT NULL COMMENT '城市面积',
POPULATION BIGINT(16) DEFAULT NULL COMMENT '城市人口',
GROSS DOUBLE DEFAULT NULL COMMENT '生产总值',
CITY_DESCRIBE VARCHAR(512) COLLATE utf8_bin DEFAULT NULL COMMENT '城市描述',
DATA_YEAR VARCHAR(16) COLLATE utf8_bin DEFAULT NULL COMMENT '数据年份',
UPDATE_TIME DATETIME DEFAULT NULL COMMENT '更新时间'
) ENGINE=INNODB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='城市信息表';
2.插入语句
插入语句,插入数据便于验证查询、更新、删除功能。
INSERT INTO t_city (
ID,CITY_NAME,LAND_AREA,POPULATION,
GROSS,CITY_DESCRIBE,DATA_YEAR,UPDATE_TIME)
VALUES
('1','杭州','16850','1200','1.61','杭州是一个好城市','2020','2022-07-23 16:39:16'),
('2','杭州','16850','1200','1.81','杭州是一个好城市','2021','2022-07-23 16:39:16');
六、JdbcTemplate源码窥探
JdbcTemplate源码调用逻辑,以queryForList的如下函数为例。
public List<Map<String, Object>> queryForList(String sql, @Nullable Object... args);
1.初始化JdbcTemplate
创建JdbcTemplate实例对象,
(1)可以设置fetchSize,每次加载条数。
(2)可以设置queryTimeout,执行SQL的超时时间,减低超时锁表等风险。
(3)可以设置maxRows,限制查询最大条数。降低大数据量拖库风险。
/**
* 获取一个JdbcTemplate实例对象
*/
public static JdbcTemplate getJdbcTemplate() {
String username = "***自定义填写**";
String password = "***自定义填写**";
String jdbcUrl = "jdbc:mysql://127.0.0.1:3306/***自定义填写**";
String driverName = "com.mysql.cj.jdbc.Driver";
DruidDataSource dataSource = new DruidDataSource();
dataSource.setPassword(password);
dataSource.setUrl(jdbcUrl);
dataSource.setUsername(username);
dataSource.setDriverClassName(driverName);
JdbcTemplate jdbcTemplate = new JdbcTemplate();
jdbcTemplate.setDataSource(dataSource);
return jdbcTemplate;
}
2.调用queryForList
调用queryForList,具体可以查看queryForList举例。
(1)调用query函数。
(2)调用getColumnMapRowMapper,会创建ColumnMapRowMapper对数据库数据集以字段名称和字段值映射到Map的key和value中。
public List<Map<String, Object>> queryForList(String sql, @Nullable Object... args) throws DataAccessException {
return this.query(sql, args, this.getColumnMapRowMapper());
}
3.调用query
调用query,创建RowMapperResultSetExtractor,处理结果集的实例对象。
public <T> List<T> query(String sql, @Nullable Object[] args, RowMapper<T> rowMapper) throws DataAccessException {
return (List)result(this.query((String)sql, (Object[])args, (ResultSetExtractor)(new RowMapperResultSetExtractor(rowMapper))));
}
4.调用query
调用query,创建ArgumentPreparedStatementSetter,处理参数的实例对象。
public <T> T query(String sql, @Nullable Object[] args, ResultSetExtractor<T> rse) throws DataAccessException {
return this.query(sql, this.newArgPreparedStatementSetter(args), rse);
}
5.调用query
调用query,创建SimplePreparedStatementCreator,处理SQL的实例对象。
public <T> T query(String sql, @Nullable PreparedStatementSetter pss, ResultSetExtractor<T> rse) throws DataAccessException {
return this.query((PreparedStatementCreator)(new JdbcTemplate.SimplePreparedStatementCreator(sql)), (PreparedStatementSetter)pss, (ResultSetExtractor)rse);
}
6.调用query
调用query,在此函数中做如下操作
6.1创建PreparedStatementCallback匿名对象
创建PreparedStatementCallback接口的匿名对象,实现doInPreparedStatement方法。
(1)设置PreparedStatementSetter对应关系
(2)执行PreparedStatement的executeQuery函数执行SQL
(3)获取执行结果集ResultSet,executeQuery执行后即返回结果集。
(4)执行ResultSetExtractor的extractData处理结果集
(5)执行JdbcUtils.closeResultSet关闭结果集
6.2执行execute函数
步骤一中的PreparedStatementCallback接口的匿名对象实现类传入execute函数具体执行。
public <T> T query(PreparedStatementCreator psc, @Nullable final PreparedStatementSetter pss, final ResultSetExtractor<T> rse) throws DataAccessException {
Assert.notNull(rse, "ResultSetExtractor must not be null");
this.logger.debug("Executing prepared SQL query");
return this.execute(psc, new PreparedStatementCallback<T>() {
@Nullable
public T doInPreparedStatement(PreparedStatement ps) throws SQLException {
ResultSet rs = null;
Object var3;
try {
if (pss != null) {
pss.setValues(ps);
}
rs = ps.executeQuery();
var3 = rse.extractData(rs);
} finally {
JdbcUtils.closeResultSet(rs);
if (pss instanceof ParameterDisposer) {
((ParameterDisposer)pss).cleanupParameters();
}
}
return var3;
}
}, true);
}
7.execute函数
调用execute函数,做具体操作。
7.1获取SQL语句
从PreparedStatementCreator对象中获取处理过的SQ语句。
7.2 获取连接对象Connection
Connection对象是java.sql.Connection,是Java原生操作数据库的连接类。获取数据库数据源连接信息。
7.3 创建PreparedStatement对象
创建PreparedStatement实例对象,根据连接信息和Connection对象创建PreparedStatement实例对象。
7.4 执行PreparedStatementCallback的doInPreparedStatement
PreparedStatementCallback接口对象在入参时候,以匿名对象方式做了实现类。执行6.1步骤中定义的流程。
1>设置PreparedStatementSetter对应关系
2>执行PreparedStatement的executeQuery函数执行SQL
3>获取执行结果集ResultSet,executeQuery执行后即返回结果集。
4>执行ResultSetExtractor的extractData处理结果集
5>执行JdbcUtils.closeResultSet关闭结果集
6>结果集以Object类型返回
7.5 获取结果集对象Object
结果集对象Object,即执行PreparedStatementCallback的doInPreparedStatement的返回值。
7.6 异常处理(catch)
在catch中做异常处理,如果执行过程抛出异常。
1>使用JdbcUtils.closeStatement关闭PreparedStatement对象。
2>使用DataSourceUtils.releaseConnection释放连接,释放资源。
3>抛出异常给调用者,去捕获处理。
7.7 finally处理
1>使用JdbcUtils.closeStatement关闭PreparedStatement对象。
2>使用DataSourceUtils.releaseConnection释放连接,释放资源。
private <T> T execute(PreparedStatementCreator psc, PreparedStatementCallback<T> action, boolean closeResources) throws DataAccessException {
Assert.notNull(psc, "PreparedStatementCreator must not be null");
Assert.notNull(action, "Callback object must not be null");
if (this.logger.isDebugEnabled()) {
String sql = getSql(psc);
this.logger.debug("Executing prepared SQL statement" + (sql != null ? " [" + sql + "]" : ""));
}
Connection con = DataSourceUtils.getConnection(this.obtainDataSource());
PreparedStatement ps = null;
Object var14;
try {
ps = psc.createPreparedStatement(con);
this.applyStatementSettings(ps);
T result = action.doInPreparedStatement(ps);
this.handleWarnings((Statement)ps);
var14 = result;
} catch (SQLException var11) {
if (psc instanceof ParameterDisposer) {
((ParameterDisposer)psc).cleanupParameters();
}
String sql = getSql(psc);
psc = null;
JdbcUtils.closeStatement(ps);
ps = null;
DataSourceUtils.releaseConnection(con, this.getDataSource());
con = null;
throw this.translateException("PreparedStatementCallback", sql, var11);
} finally {
if (closeResources) {
if (psc instanceof ParameterDisposer) {
((ParameterDisposer)psc).cleanupParameters();
}
JdbcUtils.closeStatement(ps);
DataSourceUtils.releaseConnection(con, this.getDataSource());
}
}
return var14;
}
以下步骤,已经是比较底层内容了。
8.窥探execute函数底层调用
8.1调用getConnection获取Connection
使用DataSourceUtils.getConnection获取Connection。
底层调用dataSource.getConnection(),即javax.sql.DataSource的方法。
8.2调用executeQuery
executeQuery函数是实现java.sql.PreparedStatement底层接口函数。
本例实现类是:com.mysql.cj.jdbc.PreparedStatementWrapper,即MySQL驱动包里面类,例如下:
public ResultSet executeQuery() throws SQLException {
ResultSet rs = null;
try {
if (this.wrappedStmt == null) {
throw SQLError.createSQLException(Messages.getString("Statement.AlreadyClosed"), "S1000", this.exceptionInterceptor);
}
rs = ((PreparedStatement)this.wrappedStmt).executeQuery();
((ResultSetInternalMethods)rs).setWrapperStatement(this);
} catch (SQLException var3) {
this.checkAndFireConnectionError(var3);
}
return rs;
}
8.3调用extractData
调用extractData,即org.springframework.jdbc.core.RowMapperResultSetExtractor
本质上还是去遍历ResultSet结果集去包装返回值,
ResultSet,即java.sql.ResultSet,也是底层原始Java的类。
public List<T> extractData(ResultSet rs) throws SQLException {
List<T> results = this.rowsExpected > 0 ? new ArrayList(this.rowsExpected) : new ArrayList();
int var3 = 0;
while(rs.next()) {
results.add(this.rowMapper.mapRow(rs, var3++));
}
return results;
}
以上,感谢。
2022年8月6日