SpingData-JDBC(新手入门指南)

JdbcTemplate 的基本使用

写在前面:
SpingData-JDBC(新手入门指南)_第1张图片
当DDL操作时,一般是用execute方法,这也是一种规范吧,这个也可以运行DML但是通常来说我DML操作是需要返回值的,一般就是返回影响的行数。然后这篇文章主要介绍增删改查,因为表格的创建一般已经完成了。

查询

  1. query 方法
    SpingData-JDBC(新手入门指南)_第2张图片
    从描述我们可以清楚的看到,普通的query 方法执行静态sql,使用的是Statement,如果需要使用PreparedStatement,可以看到还有一个方法query(String, Object[], ResultSetExtractor),只需要将数据参数传为null即可。
    使用ResultSetExtractor是一个函数式接口,它定义了查询到的结果如何提取。
public List<Foo> demoQuery() {
    List<Foo> result = jdbcTemplate.query("SELECT ID,BAR FROM foo", (rs) -> {
        List<Foo> res = new ArrayList<>();
        while (rs.next()) {
            Long id = rs.getLong(1);
            String bar = rs.getString("BAR");
            Foo foo = new Foo(id, bar);
            res.add(foo);
        }
        return res;
    });
    return result;
}

使用行处理器RowCallbackHandler,定义了每一行需要执行怎样的逻辑

public List<Foo> demoQuery() {
   List<Foo> result = new ArrayList<>();
   jdbcTemplate.query("SELECT ID,BAR FROM foo", (rs) -> {
           Long id = rs.getLong(1);
           String bar = rs.getString("BAR");
           Foo foo = new Foo(id, bar);
           result.add(foo);
       }
   );
   return result;
}

使用PreparedStatement

正如上面描述所说,上面的两段代码使用的是Statement,下面演示一下PreparedStatement的用法:

public List<Foo> demoQuery1() {
 List<Foo> result = jdbcTemplate.query("SELECT ID,BAR FROM foo WHERE ID IN (?,?,?)" ,new Object[]{2,3,4}, (rs) -> {
     List<Foo> res = new ArrayList<>();
     while (rs.next()) {
         Long id = rs.getLong(1);
         String bar = rs.getString("BAR");
         Foo foo = new Foo(id, bar);
         res.add(foo);
     }
     return res;
 });
 return result;
}

List query(String sql, RowMapper rowMapper) 这个方法就是有一个RowMapper 将数据映射为我们需要的数据,比如映射为一个Map

// ColumnMapRowMapper Spring JDBC 提供的一个实现
// 这里的实现完全和public Map queryForMap(String sql); 这个方法一样,只是这个方法把转换的Mapper 写到了里面
List<Map<String, Object>> resultMap = jdbcTemplate.query("SELECT ID,BAR FROM foo", new ColumnMapRowMapper());

在这里插入图片描述

当然也可以自定义:

// 同样使用lamada 表达式
List<Foo> foos = jdbcTemplate.query("SELECT ID,BAR FROM foo", (rs, rowIndex) -> {
    long id = rs.getLong("ID");
    String bar = rs.getString("BAR");
    Foo foo = new Foo(id, bar);
    return foo;
});

这是第一部分,相当于是对于数据的映射需要我们自己来处理,jdbcTemplate提供了一写其它方法比如queryForObject,queryForList 但是不太好用,因为默认映射是单列的如下:
T queryForObject(String sql, Class requiredType)
List queryForList(String sql, Object[] args, int[] argTypes, Class elementType)
在这里插入图片描述
在这里插入图片描述
可以看到里面都是用了SingleColumnRowMapper所以这两个方法不太好用,如果列数量超过了1就会抛出异常,只适合返回一个字段的场景

List<String> foos = jdbcTemplate.queryForList("SELECT BAR FROM foo", String.class);

如果需要映射为对象还是需要用ResultSetExtractor或RowCallbackHandler,或者直接使用jdbcTemplate提供的下面这个方法,返回一个Map的集合,它使用的就是ColumnMapRowMapper:

public List<Map<String, Object>> queryForList(String sql) throws DataAccessException {
	return query(sql, getColumnMapRowMapper());
}

插入

1) 使用update 这一类方法进行插入或更新,文档描述直接写了的
SpingData-JDBC(新手入门指南)_第3张图片
普通的使用

public Object demoInsert() {
    String sql = "INSERT INTO FOO (ID,BAR) VALUES('100','HHH')";
    // 返回的是插入以后影响的行数
    int update = jdbcTemplate.update(sql);
    return update;
}

预编译SQL

public Object demoInsert() {
     String sql = "INSERT INTO FOO (ID,BAR) VALUES(?,?)";
     // 返回的是插入以后影响的行数
     int update = jdbcTemplate.update(sql, new Object[]{100, "hhh"});
     // 当然也是可以直接写参数的,这种直接写更常用
     int update = jdbcTemplate.update(sql, 200,"mmm");
     return update;
 }

也可以不通过参数列表的形式,而是直接传递一个PreparedStatementSetter

public Object demoInsert() {
    String sql = "INSERT INTO FOO (ID,BAR) VALUES(?,?)";
    Map<String, Object> map = new HashMap<String,Object>(){{
        put("ID", 100);
        put("BAR", "bar");
    }};
    // 返回的是插入以后影响的行数
    int update = jdbcTemplate.update(sql, (ps) -> {
        ps.setObject(1, map.get("ID"));
        ps.setObject(2, map.get("BAR"));
    });
    return update;
}

2)SimpleJdbcInsert 这是包里面提供了一个类也可以做插入的操作,某些场景下可能还是比较方便的
首先我们需要注入将这个bean注入到容器

@Bean
@Autowired
public SimpleJdbcInsert simpleJdbcInsert(JdbcTemplate jdbcTemplate) {
	return new SimpleJdbcInsert(jdbcTemplate)
		 // 这里指定了bean 同时指定了主键自增策略
		.withTableName("FOO").usingGeneratedKeyColumns("ID");
}

插入后返回主键

public Number insertData() {
        Map<String, Object> row = new HashMap<>();
        row.put("bar", "c");
        // 插入后返回主键
        Number number = simpleJdbcInsert.executeAndReturnKey(row);
        return number;
    }

executeAndReturnKey 方法需要的参数是列名和值的map映射集合。

更新

更新用的方法依然是updata这一类函数,返回的同样是受影响的函数

public Object demoUpdate() {
  String sql = "UPDATE  FOO SET BAR = ? WHERE ID = ?";
  // 返回的是插入以后影响的行数
  int update = jdbcTemplate.update(sql, "UP", 2);
  int update = jdbcTemplate.update(sql, new Object[]{2,"up"});
  return update;
}

和插入基本差不多的,也可以像下面这么写:

public Object demoUpdate() {
   String sql = "UPDATE  FOO SET BAR = ? WHERE ID = ?";
   Map<String, Object> map = new HashMap<String,Object>(){{
       put("ID", 2);
       put("BAR", "TTT");
   }};
   // 返回的是插入以后影响的行数
   int update = jdbcTemplate.update(sql, (ps) -> {
       ps.setObject(2, map.get("ID"));
       ps.setObject(1, map.get("BAR"));
   });
   return update;
}

删除

删除操作

public void demoDelete() {
    String sql = "DELETE FROM foo WHERE ID= ?";
    int update = jdbcTemplate.update(sql, 2);
    System.out.println(update);
}

批量

对于批量操作来说,主要是批量更新和批量插入操作。
1)使用NamedParameterJdbcTemplate

@Bean
@Autowired
public NamedParameterJdbcTemplate namedParameterJdbcTemplate(DataSource dataSource) {
	return new NamedParameterJdbcTemplate(dataSource);
}

插入注入NamedParameterJdbcTemplate 后可以批量插入

@Autowired
private NamedParameterJdbcTemplate namedParameterJdbcTemplate;
List<Foo> list = new ArrayList<>();
        list.add(Foo.builder().id(100L).bar("b-100").build());
        list.add(Foo.builder().id(101L).bar("b-101").build());
        namedParameterJdbcTemplate
                .batchUpdate("INSERT INTO FOO (ID, BAR) VALUES (:id, :bar)",
                        SqlParameterSourceUtils.createBatch(list));

2 使用JdbcTemplate

public void batchInsert() {
       List<Foo> foos = new ArrayList<Foo>(){{
           add(new Foo(100L, "10t0"));
           add(new Foo(200L, "20t0"));
           add(new Foo(300L, "30t0"));
       }};
       jdbcTemplate.batchUpdate("INSERT INTO FOO (ID,BAR) VALUES (?,?)",
               new BatchPreparedStatementSetter() {
                   @Override
                   public void setValues(PreparedStatement ps, int i) throws SQLException {
                       ps.setObject(1, foos.get(i).getId());
                       ps.setObject(2, foos.get(i).getBar());
                   }
                   @Override
                   public int getBatchSize() {
                       return 3;
                   }
               });
}

你可能感兴趣的:(Java,数据库,学习笔记,数据库,jdbc,jdbctemplate,spring,jdbc)