JdbcTemplate(NamedParameterJdbcTemplate)详解
Spring对数据库的操作在jdbc上⾯做了深层次的封装,提供了JdbcTemplate模板。
传统Jdbc API与Spring jdbcTemplate⽐较:
//JDBC API
Statement statement = ateStatement();
ResultSet resultSet = uteQuery("select count(*) from COUNT student")
()){
Integer count = Int("COUNT");
}
//JDBC Template
Integer count = jdbcTemplate.queryForObject("select count(*) from student",Integer.class);
execute⽅法:可以⽤于执⾏任何SQL语句,⼀般⽤于执⾏DDL语句;
update⽅法及batchUpdate⽅法:update⽅法⽤于执⾏新增、修改、删除等语句;batchUpdate⽅法⽤于执⾏批处理相关语句;
query⽅法及queryForXXX⽅法:⽤于执⾏查询相关语句;
call⽅法:⽤于执⾏存储过程、函数相关语句(了解即可)。
//update操作单个增删改
int update(String sql,Object[] args)
int update(String 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> 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> arg)
查询复杂对象(封装为Map):
//获取单个
Map queryForMap(String sql)
Map queryForMap(String sql,Objcet[] args)
Map queryForMap(String arg)
//获取多个
List<Map<String,Object>> queryForList(String sql)
List<Map<String,Object>> queryForList(String sql,Obgject[] args)
List<Map<String,Object>> queryForList(String arg)
查询复杂对象(封装为实体对象):
Spring JdbcTemplate是通过实现org.RowMapper这个接⼝来完成对entity对象映射。
//获取单个
T queryForObject(String sql,RowMapper<T> mapper)
T queryForObject(String sql,object[] args,RowMapper<T> mapper)
T queryForObject(String sql,RowMapper<T> 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> arg)
pring JDBC中⽬前有两个主要的RowMapper实现,使⽤它们应该能解决⼤部分的场景了:SingleColumnRowMapper和BeanPropertyRowMapper。
SingleColumnRowMapper:返回单列数据
BeanPropertyRowMapper:当查询数据库返回的是多列数据,且需要将这些多列数据映射到某个具体的实体类上。
//⽰例:
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。
//⾃定义
public class StudentRowMapper implements RowMapper<Student> {
@Override
public Student mapRow(ResultSet rs, int i) throws SQLException {
Student student = new Student();
student.String("name"));
student.String("gender"));
student.String("email"));
return student;
}
}
//使⽤
String sql = "select name, gender, email from test_student where name = ?";
1. 预编译语句及存储过程创建回调:⽤于根据JdbcTemplate提供的连接创建相应的语句
PreparedStatementCreator:通过回调获取JdbcTemplate提供的Connection,由⽤户使⽤该Conncetion创建相关的PreparedStatement;CallableStatementCreator:通过回调获取JdbcTemplate提供的Connection,由⽤户使⽤该Conncetion创建相关的CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.JdbcTemplate;
import org.PreparedStatementCallback;
import org.PreparedStatementCreator;
import st.context.ContextConfiguration;
import st.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class) // 关联Spring与Junit
@ContextConfiguration(locations = { "l" }) // 加载配置spring配置⽂件
public class AppTest {
@Autowired
private JdbcTemplate jdbcTemplate;
@Test
public void testPpreparedStatement1() {
int count = ute(new PreparedStatementCreator() {
public java.sql.PreparedStatement createPreparedStatement(Connection conn) throws SQLException {
return conn.prepareStatement("select count(*) from user");
}
}, new PreparedStatementCallback<Integer>() {
public Integer doInPreparedStatement(java.sql.PreparedStatement pstmt)
throws SQLException, DataAccessException {
ResultSet rs = ResultSet();
<();
Int(1);
}
});
System.out.println(count);
}
}
⾸先使⽤PreparedStatementCreator创建⼀个预编译语句,其次由JdbcTemplate通过PreparedStatementCallback回调传回,由⽤户决定如何执⾏该PreparedStatement。此处我们使⽤的是execute⽅法。以下是我们mysql中常⽤的插⼊时返回⾃增的主键:
public long queryBuildingInfo(Map<String, Object> map) {
String sql = "INSERT INTO TS_DEVICE_CHANGE(DEVICE_ID,CHANGE_DEVICE_ID)VALUES(?,?) ";
KeyHolder keyHolder = new GeneratedKeyHolder();
jdbcTemplate.update(new PreparedStatementCreator() {
@Override
public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
jdbctemplate insert// 设置返回的主键字段名
PreparedStatement ps = con.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
ps.setString(1, "1");
ps.setString(2, "2");
return ps;
}
}, keyHolder);
// 获取到插⼊数据⽣成的ID
Key().longValue();
}
2. 预编译语句设值回调:⽤于给预编译语句相应参数设值
PreparedStatementSetter:通过回调获取JdbcTemplate提供的PreparedStatement,由⽤户来对相应的预编译语句相应参数设值;BatchPreparedStatementSetter:;类似于PreparedStatementSetter,但⽤于批处理,需要指定批处理⼤⼩;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.JdbcTemplate;
import org.PreparedStatementSetter;
import st.context.ContextConfiguration;
import st.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class) // 关联Spring与Junit
@ContextConfiguration(locations = { "l" }) // 加载配置spring配置⽂件
public class AppTest {
@Autowired
private JdbcTemplate jdbcTemplate;
@Test
public void testPreparedStatement2() {
String insertSql = "insert into user(user_name) values (?)";
int count = jdbcTemplate.update(insertSql, new PreparedStatementSetter() {
public void setValues(PreparedStatement pstmt) throws SQLException {
pstmt.setObject(1, "mmNN");
}
});
Assert.assertEquals(1, count);
String deleteSql = "delete from user where user_name=?";
count = jdbcTemplate.update(deleteSql, new Object[] { "mmNN" });
Assert.assertEquals(1, count);
}
}
通过JdbcTemplate的int update(String sql, PreparedStatementSetter pss)执⾏预编译sql,其中sql参数为“insert into user(user_name) values (?) ”,该sql有⼀个占位符需要在执⾏前设值,PreparedStatementSetter实现就是为了设值,使⽤setValues(PreparedStatement
pstmt)回调⽅法设值相应的占位符位置的值。JdbcTemplate也提供⼀种更简单的⽅式“update(String sql, args)”来实现设值,所以只要当使⽤该种⽅式不满⾜需求时才应使⽤PreparedStatementSetter。
3. ⾃定义功能回调:提供给⽤户⼀个扩展点,⽤户可以在指定类型的扩展点执⾏任何数量需要的操作
ConnectionCallback:通过回调获取JdbcTemplate提供的Connection,⽤户可在该Connection执⾏任何数量的操作;StatementCallback:通过回调获取JdbcTemplate提供的Statement,⽤户可以在该Statement执⾏任何数量的操作;PreparedStatementCallback:通过回调获取JdbcTemplate提供的PreparedStatement,⽤户可以在该PreparedStatement执⾏任何数量的操作;
CallableStatementCallback:通过回调获取JdbcTemplate提供的CallableStatement,⽤户可以在该CallableStatement执⾏任何数量的操作;
4. 结果集处理回调:通过回调处理ResultSet或将ResultSet转换为需要的形式
RowMapper:⽤于将结果集每⾏数据转换为需要的类型,⽤户需实现⽅法mapRow(ResultSet rs, int rowNum)来完成将每⾏数据转换为相应的类型。
RowCallbackHandler:⽤于处理ResultSet的每⼀⾏结果,⽤户需实现⽅法processRow(ResultSet rs)来完成处理,在该回调⽅法中⽆需执⾏rs.next(),该操作由JdbcTemplate来执⾏,⽤户只需按⾏获取数据然后处理即可。
ResultSetExtractor:⽤于结果集数据提取,⽤户需实现⽅法extractData(ResultSet rs)来处理结果集,⽤户必须处理整个结果集;
@Test
public void testResultSet1() {
jdbcTemplate.update("insert into user(user_name) values('name7')");
String listSql = "select * from user where user_name=?";
List result = jdbcTemplate.query(listSql,new Object[]{"name7"}, new RowMapper<Map>() {
public Map mapRow(ResultSet rs, int rowNum) throws SQLException {
Map row = new HashMap();
row.Int("user_id"), rs.getString("user_name"));
return row;
}
});
Assert.assertEquals(1, result.size());//查询结果数量为1才向下执⾏
jdbcTemplate.update("delete from user where user_name='name7'");
}
RowMapper接⼝提供mapRow(ResultSet rs, int rowNum)⽅法将结果集的每⼀⾏转换为⼀个Map,当然可以转换为其他类。
@Test
public void testResultSet2() {
jdbcTemplate.update("insert into user(user_name) values('name5')");
String listSql = "select * from user";
final List result = new ArrayList();
jdbcTemplate.query(listSql, new RowCallbackHandler() {
public void processRow(ResultSet rs) throws SQLException {
Map row = new HashMap();
row.Int("user_id"), rs.getString("user_name"));
result.add(row);
}
});
Assert.assertEquals(1, result.size());
jdbcTemplate.update("delete from user where user_name='name5'");
}
RowCallbackHandler接⼝也提供⽅法processRow(ResultSet rs),能将结果集的⾏转换为需要的形式。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论