jbcTemplate
Spring对数据库的操作在jdbc上面做了深层次的封装,提供了JdbcTemplate模板。只需要把DataSource注册到JdbcTemplate之中,其全限定命名为org.springframework.jdbc.core.JdbcTemplate。要使用JdbcTemlate一般还需要事务和异常的控制。
java
//JDBC API
Statement statement = conn.createStatement();
ResultSet resultSet = statement.executeQuery("select count(*) from COUNT student")
if(resultSet.next()){
Integer count = resultSet.getInt("COUNT");
}
//JDBC Template
Integer count = jdbcTemplate.queryForObject("select count(*) from student",Integer.class);
JdbcTemplate主要几类方法
- execute方法:可以用于执行任何SQL语句,一般用于执行DDL语句;
- update方法及batchUpdate方法:update方法用于执行新增、修改、删除等语句;batchUpdate方法用于执行批处理相关语句;
- query方法及queryForXXX方法:用于执行查询相关语句;
- call方法:用于执行存储过程、函数相关语句(了解即可)。
JdbcTemplate常用API
java
//update操作单个增删改
int update(String sql,Object[] args)
int update(String sql,Objcet... args)
//batchUpdate批量增删改
int[] batchUpdate(String[] sql)
int[] batchUpdate(String sql,List<Object[]>)
//单个简单查询
T queryForObjcet(String sql,Class<T> type)
T queryForObjcet(String sql,Object[] args,Class<T> type)
T queryForObjcet(String sql,Class<T> type,Object... arg)
//获取多个
List<T> queryForList(String sql,Class<T> type)
List<T> queryForList(String sql,Object[] args,Class<T> type)
List<T> queryForList(String sql,Class<T> type,Object... arg)
查询复杂对象(封装为Map):
java
//获取单个
Map queryForMap(String sql)
Map queryForMap(String sql,Objcet[] args)
Map queryForMap(String sql,Object... arg)
//获取多个
List<Map<String,Object>> queryForList(String sql)
List<Map<String,Object>> queryForList(String sql,Obgject[] args)
List<Map<String,Object>> queryForList(String sql,Obgject... arg)
查询复杂对象(封装为实体对象):
Spring JdbcTemplate是通过实现org.springframework.jdbc.core.RowMapper这个接口来完成对entity对象映射。
java
//获取单个
T queryForObject(String sql,RowMapper<T> mapper)
T queryForObject(String sql,object[] args,RowMapper<T> mapper)
T queryForObject(String sql,RowMapper<T> mapper,Object... arg)
//获取多个
List<T> query(String sql,RowMapper<T> mapper)
List<T> query(String sql,Object[] args,RowMapper<T> mapper)
List<T> query(String sql,RowMapper<T> mapper,Object... arg)
Spring JDBC中目前有两个主要的RowMapper实现,使用它们应该能解决大部分的场景了:SingleColumnRowMapper和BeanPropertyRowMapper。
SingleColumnRowMapper:返回单列数据
BeanPropertyRowMapper:当查询数据库返回的是多列数据,且需要将这些多列数据映射到某个具体的实体类上。
java
//示例:
String sql = "select name from test_student where id = ?";
jdbcTemplate.queryForObject(sql, new Object[]{id}, new SingleColumnRowMapper<>(String.class));
String sql = "select name, gender from test_student where name = ?";
jdbcTemplate.queryForObject(sql, new Object[]{name},new BeanPropertyRowMapper<>(Student.class));
定义自己的RowMapper
如果你SQL查询出来的数据列名就是和实体类的属性名不一样,或者想按照自己的规则来装配实体类,那么就可以定义并使用自己的Row Mapper。
java
//自定义
public class StudentRowMapper implements RowMapper<Student> {
@Override
public Student mapRow(ResultSet rs, int i) throws SQLException {
Student student = new Student();
student.setName(rs.getString("name"));
student.setGender(rs.getString("gender"));
student.setEmail(rs.getString("email"));
return student;
}
}
//使用
String sql = "select name, gender, email from test_student where name = ?";
jdbcTemplate.queryForObject(sql, new Object[]{name}, new StudentRowMapper());
批量修改
java
public int[] batchInsert(List<Map<String, Object>> dataList) {
String sql = "INSERT INTO test_info(name, create_time, age) VALUES(?, NOW(), ?)";
List<Object[]> paramArray = new ArrayList<>();
for (Map<String, Object> dataInfo : dataList) {
Object[] obj = new Object[2];
obj[0] = dataInfo.get("name");
obj[1] = dataInfo.get("age");
paramArray.add(obj);
}
if (CollectionUtils.isNotEmpty(paramArray)) {
return jdbcTemplate.batchUpdate(sql, paramArray);
}
return new int[0];
}
JdbcTemplate提供更简单的queryForXXX方法,来简化开发:
java
//1.查询一行数据并返回int型结果
jdbcTemplate.queryForInt("select count(*) from test");
//2. 查询一行数据并将该行数据转换为Map返回
jdbcTemplate.queryForMap("select * from test where name='name5'");
//3.查询一行任何类型的数据,最后一个参数指定返回结果类型
jdbcTemplate.queryForObject("select count(*) from test", Integer.class);
//4.查询一批数据,默认将每行数据转换为Map
jdbcTemplate.queryForList("select * from test");
//5.只查询一列数据列表,列类型是String类型,列名字是name
jdbcTemplate.queryForList("
select name from test where name=?", new Object[]{"name5"}, String.class);
//6.查询一批数据,返回为SqlRowSet,类似于ResultSet,但不再绑定到连接上
SqlRowSet rs = jdbcTemplate.queryForRowSet("select * from test");
namedParameterJdbcTemplate详解
具名参数
在经典的 JDBC 用法中, SQL 参数是用占位符 ? 表示,并且受到位置的限制。定位参数的问题在于, 一旦参数的顺序发生变化, 就必须改变参数绑定。
在 Spring JDBC 框架中, 绑定 SQL 参数的另一种选择是使用具名参数(named parameter)。
具名参数:SQL 按名称(以冒号开头)而不是按位置进行指定,具名参数更易于维护,,也提升了可读性。具名参数由框架类在运行时用占位符取代,
具名参数只在 NamedParameterJdbcTemplate 中得到支持。
NamedParameterJdbcTemplate类拓展了JdbcTemplate类,可以使用全部jdbcTemplate方法。
NamedParameterJdbcTemplate主要提供以下三类方法:execute方法、query及queryForXXX方法、update及batchUpdate方法。
NamedParameterJdbcTemplate可以使用DataSource或JdbcTemplate 对象作为构造器参数初始化。
初始化方法
java
// 声明dataSource
@Bean(name = "payDataSource")
@ConfigurationProperties(prefix = "spring.xxx.xxxx")
public DataSource payDataSource() {
return DataSourceBuilder.create().build();
}
// 声明template
@Bean(name = "payTemplate")
public NamedParameterJdbcTemplate payTemplate(@Qualifier("payDataSource") DataSource dataSource) {
return new NamedParameterJdbcTemplate(dataSource);
}
// 注入payTemplate
@Resource(name = "payTemplate")
private NamedParameterJdbcTemplate jdbcTemplate;
常用API传入参数类型介绍
NamedParameterJdbcTemplate类为命名参数设值有两种方式:java.util.Map 、RowMapper 和 SqlParameterSource。
Map<String,?> paramMap
就是一个hash表,好处是可以根据参数名传参,paramMap.put("sqlparamName",value)。
RowMapper rowMapper
这个接口为了实现sql查询结果和对象间的转换,可以自己实现,也可以使用系统实现,主要实现类有:
- SingleColumnRowMapper ,sql结果为一个单列的数据,如List<String> , List<Integer>,String,Integer等
- BeanPropertyRowMapper, sql结果匹配到对象 List< XxxVO> , XxxVO
SqlParameterSource
其作用和Map一样,就是为sql中的条件参数赋值,默认实现有 :
- MapSqlParameterSource实现非常简单,只是封装了java.util.Map。
- BeanPropertySqlParameterSource封装了一个JavaBean对象,通过JavaBean对象属性来决定命名参数的值。
- EmptySqlParameterSource 一个空的SqlParameterSource ,常用来占位使用。
java
//BeanPropertySqlParameterSource传参方式
SqlParameterSource sps = new BeanPropertySqlParameterSource(javaBean);
//MapSqlParameterSource传参方式
SqlParameterSource sps = new MapSqlParameterSource();
//保证参数名和key相同
sps.addValue("key",value);
API介绍
查询
返回单行单列数据
java
public < T > T queryForObject(String sql, Map<String, ?> paramMap, Class<T> requiredType)
public < T > T queryForObject(String sql, SqlParameterSource paramSource, Class<T> requiredType)
Integer count = template.queryForObject("select count(*) from student", new HashMap<>(), Integer.class);
String name = template.queryForObject( "select name from student where home_address limit 1 ", EmptySqlParameterSource.INSTANCE, String.class);
返回 (多行)单列 数据
java
public < T> List< T> queryForList(String sql, Map<String, ?> paramMap, Class< T > elementType)
public < T> List< T> queryForList(String sql, SqlParameterSource paramSource, Class< T> elementType)
List< String> namelist = template.queryForList("select name from student", new HashMap<>(), String.class);
返回单行多列数据
java
public < T> T queryForObject(String sql, Map< String, ?> paramMap, RowMapper< T>rowMapper)
public < T> T queryForObject(String sql, SqlParameterSource paramSource, RowMapper< T> rowMapper)
Student stu = template.queryForObject(
"select * from student limit 1", new HashMap<>(), new BeanPropertyRowMapper<Student>(Student.class));
//BeanPropertyRowMapper会把下划线转化为驼峰属性
//结果对象可比实际返回字段多或者少
注意:这两个API也可以使用SingleColumnRowMapper返回单行单列数据
java
String name = template.queryForObject(
"select name from student limit 1", EmptySqlParameterSource.INSTANCE, new SingleColumnRowMapper<>(String.class));
返回Map形式的单行数据
java
public Map< String, Object> queryForMap(String sql, Map< String, ?> paramMap)
public Map< String, Object> queryForMap(String sql, SqlParameterSource paramSource)
Map< String, Object> studentMap = template.queryForMap("select * from student limit 1", new HashMap<>());
注意:queryForMap这个方法要求结果必须是有数据的,否则会报错。
返回多行数据
java
public < T> List< T> query(String sql, Map< String, ?> paramMap, RowMapper< T> rowMapper)
public < T> List< T> query(String sql, SqlParameterSource paramSource, RowMapper< T> rowMapper)
public < T> List< T> query(String sql, RowMapper< T> rowMapper)
List< Student> studentList = template.query(
"select * from student",
new BeanPropertyRowMapper<>(Student.class));
同理,也可以使用SingleColumnRowMapper返回单行列表List< String>,List< Integer>等。
返回多行数据(Map)
java
public List< Map< String, Object>> queryForList(String sql, Map< String, ?> paramMap)
public List< Map< String, Object>> queryForList(String sql, SqlParameterSource paramSource)
List<Map<String, Object>> mapList = template.queryForList("select * from student", new HashMap<>());
插入/修改/删除数据,使用updateXXX方法
使用Map作为参数
java
int update(String sql, Map<String, ?> paramMap)
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("id", UUID.randomUUID().toString());
paramMap.put("name", "小明");
paramMap.put("age", 33);
paramMap.put("homeAddress", "乐山");
paramMap.put("birthday", new Date());
template.update(
"insert into student(id,name,age,home_address,birthday) values (:id,:name,:age,:homeAddress,:birthday)",
paramMap
);
使用SqlParameterSource作为参数
java
int update(String sql, SqlParameterSource paramSource)
//使用 BeanPropertySqlParameterSource作为参数
StudentDTO dto=new StudentDTO();//这个DTO为传入数据
dto.setId(UUID.randomUUID().toString());
dto.setName("小红");
dto.setHomeAddress("成都");
//------------------------------
template.update("insert into student(id,name,home_address) values (:id,:name,:homeAddress)",
new BeanPropertySqlParameterSource(dto));
//使用MapSqlParameterSource 作为参数
MapSqlParameterSource mapSqlParameterSource = new MapSqlParameterSource()
.addValue("id", UUID.randomUUID().toString())
.addValue("name", "小王")
.addValue("homeAddress", "美国");
template.update("insert into student(id,name,home_address) values
(:id,:name,:homeAddress)",mapSqlParameterSource);
注意:
【query方法】返回结果是list,且list中元素必须是自定义bean;不能是list<String>。
【queryForObject】查询出一条记录并封装到一个对象中。可以返回的是String、Integer、Double或者自定义bean。但是如果查询的记录为0条或者大于1条,对不起抛出异常。
【queryForList】这个方法返回一个list,这个方法比较特殊,可以返回List<String> ,还可以返回list<Map<String,Objec>>,但是不支持返回具体DTO类。
【queryForMap】查询一行数据封装到Map中。如果查询多行记录抛出异常。
JdbcTemplate 和 NamedParameterJdbcTemplate详解 - codedot - 博客园
NamedParameterJdbcTemplate常用方法总结-CSDN博客
Jdbctemplate中query、queryForObject、queryForList、queryForMap方法使用_queryforobject怎么用-CSDN博客