基于Spring Boot应用JdbcTemplate操作数据库(查增改删)

记录: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  List query(String sql, RowMapper rowMapper);
public  List query(String sql, RowMapper rowMapper, @Nullable Object... args);
public  List query(String sql, Object[] args, int[] argTypes, RowMapper 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 list = jt.query(sql, new CityRowMapper());
    // 4.遍历结果并打印
    Stream 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 list = jt.query(sql, new CityRowMapper(), args);
    // 5.遍历结果并打印
    Stream 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 list = jt.query(sql, args, argTypes, new CityRowMapper());
    // 5.遍历结果并打印
    Stream 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 list = jt.query(sql, new BeanPropertyRowMapper<>(CityPO.class), args);
    // 5.遍历结果并打印
    Stream 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  Stream queryForStream(String sql, RowMapper rowMapper);
public  Stream queryForStream(String sql, RowMapper rowMapper, @Nullable Object... args);
public  Stream queryForStream(String sql, @Nullable PreparedStatementSetter pss, RowMapper 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 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 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 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 queryForMap(String sql);
public Map queryForMap(String sql, @Nullable Object... args);
public Map queryForMap(String sql, Object[] args, int[] argTypes);

3.2 queryForMap使用场景

场景:使用queryForMap函数,可以把查询结果集封装成Map,而且只能查询一条记录,即数据库表中一行数据。

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 map = jt.queryForMap(sql);
  // 4.遍历结果并打印
  Stream> 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 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 map = jt.queryForMap(sql, args, argTypes);
  // 5.遍历结果并打印
  for (Map.Entry 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 queryForObject(String sql, Class requiredType);
public  T queryForObject(String sql, Class requiredType, @Nullable Object... args);
public  T queryForObject(String sql, Object[] args, int[] argTypes, Class 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 queryForObject(String sql, RowMapper rowMapper);
public  T queryForObject(String sql, RowMapper rowMapper, @Nullable Object... args);
public  T queryForObject(String sql, Object[] args, int[] argTypes, RowMapper 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> queryForList(String sql)
public List> queryForList(String sql, @Nullable Object... args);
public List> queryForList(String sql, Object[] args, int[] argTypes);

6.1.2 queryForList使用场景

场景:使用queryForList函数,把查询结果集封装为List>,遍历List取出每条记录,即一条记录一个Map,一个Map对应数据库表中的字段和字段值,即Map的key,value键值对。

6.1.3 queryForList使用举例

/**
  * 1.queryForList函数入参不带查询条件,如有查询条件直接写在SQL中
  * 2.使用List>封装返回值
  * 3.使用java.util.stream.Stream遍历结果
  */
public static void f6_1_1() {
  // 1.获取查询sql
  String sql = getSelectSql01();
  // 2.获取JdbcTemplate
  JdbcTemplate jt = getJdbcTemplate();
  // 3.查询数据集
  List> list = jt.queryForList(sql);
  // 4.遍历结果并打印,使用Stream函数式遍历
  Stream> 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>封装返回值
 * 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> list = jt.queryForList(sql, args);
  // 5.遍历结果并打印,使用for遍历
  for (Map map : list) {
      for (Map.Entry entry : map.entrySet()) {
          System.out.println(entry.getKey() + " = " + entry.getValue());
      }
  }
}

/**
 * 1.queryForList函数入参带查询条件,入参带参数类型
 * 2.使用List>封装返回值
 * 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> list = jt.queryForList(sql, args, argTypes);
  // 5.遍历结果并打印,使用for遍历,和while遍历
  for (int i = 0; i < list.size(); i++) {
      Map map = list.get(i);
      Iterator> entries = map.entrySet().iterator();
      while (entries.hasNext()) {
          Map.Entry 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  List queryForList(String sql, Class elementType);
public  List queryForList(String sql, Class elementType, @Nullable Object... args);
public  List queryForList(String sql, Object[] args, int[] argTypes, Class elementType);

6.2.2 queryForList使用场景

场景:使用queryForList函数,把查询结果封装为指定的基本类型,返回值封装在 List 中。适合查询一个字段的多条记录。

6.2.3 queryForList使用举例

/**
 * 1.queryForList函数入参不带查询条件,如有查询条件直接写在SQL中
 * 2.查一个字段的多条记录,使用List封装返回值
 * 3.使用java.util.stream.Stream遍历结果
 */
public static void f6_2_1() {
  // 1.获取查询sql
  String sql = getSelectSql07();
  // 2.获取JdbcTemplate
  JdbcTemplate jt = getJdbcTemplate();
  // 3.查询数据集
  List list = jt.queryForList(sql, String.class);
  // 4.遍历结果并打印
  Stream stream = list.stream();
  stream.forEach(cityName -> {
      System.out.println(cityName.toString());
  });
}

/**
 * 1.queryForList函数入参带查询条件
 * 2.查一个字段的多条记录,使用List封装返回值
 * 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 list = jt.queryForList(sql, String.class, args);
  // 5.遍历结果并打印
  Stream stream = list.stream();
  stream.forEach(cityName -> {
      System.out.println(cityName.toString());
  });
}

/**
 * 1.queryForList函数入参带查询条件,入参带参数类型
 * 2.查一个字段的多条记录,使用List封装返回值
 * 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 list = jt.queryForList(sql, args, argTypes, String.class);
  // 5.遍历结果并打印
  Stream 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 {
  @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 batchArgs);
public int[] batchUpdate(String sql, List batchArgs, final int[] argTypes); 
public int[] batchUpdate(String sql, final BatchPreparedStatementSetter pss);
public  int[][] batchUpdate(String sql, final Collection batchArgs, final int batchSize, final ParameterizedPreparedStatementSetter 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 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 batchArgs = getInsertBatchArgs();
  // 4.执行insert语句
  int[] result = jt.batchUpdate(sql, batchArgs);
  // 5.打印返回值
  List 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 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 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 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 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 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 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 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 batchArgs);
public int[] batchUpdate(String sql, List batchArgs, final int[] argTypes);
public int[] batchUpdate(String sql, final BatchPreparedStatementSetter pss);
public  int[][] batchUpdate(String sql, final Collection batchArgs, final int batchSize, final ParameterizedPreparedStatementSetter 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 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 batchArgs = getUpdateBatchArgs();
  // 4.执行update语句
  int[] result = jt.batchUpdate(sql, batchArgs);
  // 5.打印返回值
  List 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 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 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 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 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 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 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 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 batchArgs);
public int[] batchUpdate(String sql, List batchArgs, final int[] argTypes);
public int[] batchUpdate(String sql, final BatchPreparedStatementSetter pss);
public  int[][] batchUpdate(String sql, final Collection batchArgs, final int batchSize, final ParameterizedPreparedStatementSetter 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 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 batchArgs = getDeleteBatchArgs();
  // 4.执行delete语句
  int[] result = jt.batchUpdate(sql, batchArgs);
  // 5.打印返回值
  List 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 batchArgs = getDeleteBatchArgs();
  int[] argTypes = new int[]{Types.VARCHAR, Types.BIGINT};
  // 4.执行delete语句
  int[] result = jt.batchUpdate(sql, batchArgs, argTypes);
  // 5.打印返回值
  List 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 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 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 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 getDeleteBatchArgs() {
  Object[] args1 = new Object[]{"杭州", "1"};
  Object[] args2 = new Object[]{"杭州", "2"};
  List 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> 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> queryForList(String sql, @Nullable Object... args) throws DataAccessException {
  return this.query(sql, args, this.getColumnMapRowMapper());
}

3.调用query

调用query,创建RowMapperResultSetExtractor,处理结果集的实例对象。

public  List query(String sql, @Nullable Object[] args, RowMapper rowMapper) throws DataAccessException {
   return (List)result(this.query((String)sql, (Object[])args, (ResultSetExtractor)(new RowMapperResultSetExtractor(rowMapper))));
}

4.调用query

调用query,创建ArgumentPreparedStatementSetter,处理参数的实例对象。

public  T query(String sql, @Nullable Object[] args, ResultSetExtractor rse) throws DataAccessException {
  return this.query(sql, this.newArgPreparedStatementSetter(args), rse);
}

5.调用query

调用query,创建SimplePreparedStatementCreator,处理SQL的实例对象。

public  T query(String sql, @Nullable PreparedStatementSetter pss, ResultSetExtractor 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 query(PreparedStatementCreator psc, @Nullable final PreparedStatementSetter pss, final ResultSetExtractor rse) throws DataAccessException {
Assert.notNull(rse, "ResultSetExtractor must not be null");
this.logger.debug("Executing prepared SQL query");
return this.execute(psc, new PreparedStatementCallback() {
  @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 execute(PreparedStatementCreator psc, PreparedStatementCallback 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 extractData(ResultSet rs) throws SQLException {
  List 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日

你可能感兴趣的:(L02-SpringBoot,java,spring,boot)