Spring-JDBC 操作SQL数据库
来源:互联网 发布:网络销售模式 编辑:程序博客网 时间:2024/05/16 10:10
Spring-JDBC 操作SQL数据库
1.关于org.springframework.jdbc
Java操作关系数据库,例如MySQL,可以使用数据库对应的JDBC驱动程序(如:mysql-connector-java)提供的的方法。但由于JDBC驱动提供的API使用起来每次都要编写连接、操作、关闭数据库和异常处理的模板(Template)代码,代码显得非常冗长重复,不利于集中精力处理实际问题。
org.springframework.jdbc
包中提供了经典类JdbcTemplate来简化数据库操作,它实现了JdbcOperations
接口。其实现是基于callback(回调)来实现的。并且能把JDBC的SQLException转换为更为容易理解的springframework包org.springframework.dao
中定义的异常类型。
NamedParameterJdbcTemplate包装了JdbcTemplate,提供JdbcTemplate的所有功能,由于增加了命名参数,便于编写和修改sql,使用更为方便。一般都是在xml中定义template的bean然后直接在dao中注入来使用。
在spring的application-context.xml配置文件中配置相关beans:
<context:property-placeholder location="jdbc.properties"/><bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="${jdbc.driverClassName}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/></bean><bean id="namedJdbcTemplate" class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate"> <property name="dataSource" ref="dataSource" /> </bean>
使用注解注入到DAO的实现类中:
@Resourceprivate NamedParameterJdbcTemplate namedJdbcTemplate;
或者使用代码直接创建相关beans:
MysqlDataSource dataSource = new MysqlDataSource();dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8");dataSource.setPassword("123");dataSource.setUser("mysql");NamedParameterJdbcTemplate namedJdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
2. NamedParameterJdbcTemplate的接口分析
现在看看template提供的方法:
- excute
<T> T execute(String sql, SqlParameterSource paramSource, PreparedStatementCallback<T> action)
<T> T execute(String sql, Map<String, ?> paramMap, PreparedStatementCallback<T> action)
<T> T execute(String sql, PreparedStatementCallback<T> action)
query
<T> T query(String sql, SqlParameterSource paramSource, ResultSetExtractor<T> rse)
<T> T query(String sql, Map<String, ?> paramMap, ResultSetExtractor<T> rse)
<T> T query(String sql, ResultSetExtractor<T> rse)
void query(String sql, SqlParameterSource paramSource, RowCallbackHandler rch)
void query(String sql, Map<String, ?> paramMap, RowCallbackHandler rch)
void query(String sql, RowCallbackHandler rch)
<T> List<T> query(String sql, SqlParameterSource paramSource, RowMapper<T> rowMapper)
<T> List<T> query(String sql, Map<String, ?> paramMap, RowMapper<T> rowMapper
<T> List<T> query(String sql, RowMapper<T> rowMapper)
<T> T queryForObject(String sql, SqlParameterSource paramSource, RowMapper<T> rowMapper)
<T> T queryForObject(String sql, Map<String, ?> paramMap, RowMapper<T>rowMapper)
<T> T queryForObject(String sql, SqlParameterSource paramSource, Class<T> requiredType)
<T> T queryForObject(String sql, Map<String, ?> paramMap, Class<T> requiredType)
Map<String, Object> queryForMap(String sql, SqlParameterSource paramSource)
Map<String, Object> queryForMap(String sql, Map<String, ?> paramMap)
<T> List<T> queryForList(String sql, SqlParameterSource paramSource, Class<T> elementType)
<T> List<T> queryForList(String sql, Map<String, ?> paramMap, Class<T> elementType)
List<Map<String, Object>> queryForList(String sql, SqlParameterSource paramSource)
List<Map<String, Object>> queryForList(String sql, Map<String, ?> paramMap)
SqlRowSet queryForRowSet(String sql, SqlParameterSource paramSource)
SqlRowSet queryForRowSet(String sql, Map<String, ?> paramMap)
update
int update(String sql, SqlParameterSource paramSource)
int update(String sql, Map<String, ?> paramMap)
int update(String sql, SqlParameterSource paramSource, KeyHolder generatedKeyHolder)
int update(
String sql, SqlParameterSource paramSource, KeyHolder generatedKeyHolder, String[] keyColumnNames)int[] batchUpdate(String sql, Map<String, ?>[] batchValues)
int[] batchUpdate(String sql, SqlParameterSource[] batchArgs)
查看接口参数很容易发现,所有方法的参数都包含sql,大部分包含param、callback:
String sql
SQL语句 param SqlParameterSource paramSource
、Map<String, ?> paramMap
SQL语句中的参数 callback PreparedStatementCallback<T> action
,ResultSetExtractor<T> rse
,RowCallbackHandler rch
,RowMapper<T> rowMapper
, 用于对一行数据进行映射 elementType Class<T> requiredType
返回单列数据时,指定数据类型 generatedKeyHolder KeyHolder generatedKeyHolder
返回生成的key其中,SqlParameterSource 的实现类有:
- MapSqlParameterSource:通过Map构造。
- BeanPropertySqlParameterSource:通过Bean的class构造。
RowMapper的实现类:
- BeanPropertyRowMapper:直接从Bean的class生成mapper。
- ColumnMapRowMapper:直接把ResultSet映射为Map.
最后看一下返回值:
void
: 没有返回值。T
: query时返回一行数据,excute时T可以是集合类型。List<?>
, SqlRowSet: 返回多行数据。int, int[]
: 返回执行一条SQL受影响的行数。
3. 使用示例
使用MySQL,先创建表:
CREATE TABLE `user` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `name` varchar(20) NOT NULL DEFAULT '', `age` int(10) unsigned DEFAULT NULL, `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `area_id` bigint(20) DEFAULT NULL, `mobile` varchar(20) DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
创建对应的PO(使用lombok简化setter,getter):
@Datapublic class User { private Long id; private String name; private Integer age; private Date createTime; private Long areaId; private String mobile;}
3.1 excute使用示例
excute-1,excute-2,excute-3: 注意返回值T可以是集合哦。
String sql = "select * from user where id = :id";Map<String, Object> params = Maps.newHashMap();params.put("id", 1L);User user1 = namedJdbcTemplate.execute(sql, new MapSqlParameterSource(params), new PreparedStatementCallback<User>() { public User doInPreparedStatement(PreparedStatement ps) throws SQLException, DataAccessException { ResultSet rs = ps.executeQuery(); rs.next(); return buildUser(rs); }});User user2 = namedJdbcTemplate.execute(sql, params, new PreparedStatementCallback<User>() { public User doInPreparedStatement(PreparedStatement ps) throws SQLException, DataAccessException { ResultSet rs = ps.executeQuery(); rs.next(); return buildUser(rs); }});List<User> users = namedJdbcTemplate.execute("select * from user", new PreparedStatementCallback<List<User>>() { @Override public List<User> doInPreparedStatement(PreparedStatement ps) throws SQLException, DataAccessException { ResultSet rs = ps.executeQuery(); List<User> users = Lists.newArrayList(); while (rs.next()) { users.add(buildUser(rs)); } return users; }});
如果excute不需要任何参数,也不返回值,怎么办呢? 可以返回namedJdbcTemplate内部的jdbcTemplate,它有相应的方法:
String sql = "create table mytable (id integer, name varchar(100))"; namedJdbcTemplate.getJdbcOperations().execute(sql);
3.2 query使用示例
Sql语句和参数:
String sql = "select * from user";
query-1~3:用于返回整个结果集,在excute上简单封装。1,2和3只有参数的区别,只举例3:
List<User> list = namedJdbcTemplate.query(sql, new ResultSetExtractor<List<User>>() { @Override public List<User> extractData(ResultSet rs) throws SQLException, DataAccessException { List<User> users = Lists.newArrayList(); while (rs.next()) { users.add(buildUser(rs)); } return users; }});
query-4~6类似,都是用RowCallbackHandler,只用处理一行即可。举例6:
List<User> list = namedParameterJdbcTemplate.query(sql, new RowCallbackHandler() { @Override public void processRow(ResultSet rs) throws SQLException { users.add(buildUser(rs)); } });
query-7~9类似,都是用RowMapper,只用处理一行即可,注意:可以获取到rowNum。举例9:
List<User> list = namedJdbcTemplate.query(sql, new RowMapper<User>() { @Override public User mapRow(ResultSet rs, int rowNum) throws SQLException { return buildUser(rs); } });
query-10~15,作用一样,都是返回一行数据,只是参数和返回值类型不一样而已,注意11,12的requiredType参数,
当使用11,12时,sql只能返回简单的一列数据,例如(select count(*) from user
),否则报错,查看源码其内部是调用query-10实现,并且使用的是SingleColumnRowMapper
,只支持一列数据。
query-10:使用BeanPropertySqlParameterSource, BeanPropertyRowMapper可极大简化编码。
两者都是用了反射实现映射。BeanPropertyRowMapper支持直接映射或者驼峰(camel),即: sql语句中的name直接映射到User类中的name, area_id映射到areaId。
BeanPropertySqlParameterSource则要求User类中的参数和sql中的冒号后的参数一致:areaId 对应 :areaId。
User user = new User();user.setId(1L);List<User> listUser =namedParameterJdbcTemplate.query("select * from user where id = :id", new BeanPropertySqlParameterSource(user4), new BeanPropertyRowMapper<User>(User.class) );
query-11: 只能返回基本数据。
try { List<User> users10 = namedParameterJdbcTemplate.queryForList(sql, new BeanPropertySqlParameterSource(user4), User.class);} catch (org.springframework.jdbc.IncorrectResultSetColumnCountException e) { e.printStackTrace(); // 注意此处会发生异常,只允许返回一列数据,所以只能用来返回基本数据,比如Integer,String,Long等的List,见SingleColumnRowMapper}// 只能用来返回基本数据Integer count2 = namedParameterJdbcTemplate.queryForObject("select count(1) from user where id = :id", paramMap, Integer.class);List<Long> ids = namedParameterJdbcTemplate.queryForList(sql, new BeanPropertySqlParameterSource(user4), Long.class);// 由此可见,queryForList只能用来返回基本数据哦
3.2 update使用示例
update-1~2比较简单,传入相应参数和sql即可返回影响的数据行数。略过。用于UPDATE,INSERT语句。
INSERT时如果设定了自动生成主键ID,update-3~4可以返回ID值。update-3用于一个自动生成ID,update-4可以用于多个,需要指定key的名称。
update-3:
String sql = "insert into user (name,age,area_id,mobile) values (:name,:age,:areaId,:mobile)";User user = new User();user.setAge(11);user.setAreaId(110L);user.setMobile("15997666334");user.setName("cookies");GeneratedKeyHolder generatedKeyHolder = new GeneratedKeyHolder();// 获取自动生成的idint count = namedParameterJdbcTemplate.update(sql, new BeanPropertySqlParameterSource(user), generatedKeyHolder);logger.debug("count = {}, key = {}", count, generatedKeyHolder.getKey());
update-5~6: batch update,批量操作,两个方法类似:
String sql = "insert into user (name,age,area_id,mobile) values (:name,:age,:areaId,:mobile)";@SuppressWarnings("rawtypes")Map[] batchValues = new HashMap[10];for (int i = 0; i < batchValues.length; i++) { Map v = new HashMap(); batchValues[i] = v; batchValues[i].put("name", "哈哈" + i); batchValues[i].put("age", 11 + i); batchValues[i].put("areaId", 123 + i); batchValues[i].put("mobile", "1867297999" + i);}// update-4:int[] c1 = namedParameterJdbcTemplate.batchUpdate(sql, batchValues);logger.debug("counts = {}", counts);// update-5:SqlParameterSource[] batchArgs = new SqlParameterSource[10];for (int i = 0; i < batchArgs; i++) { User user = new User(); user.setAge(11 + i); user.setAreaId(110L + i); user.setMobile("1599766633" + i); user.setName("cookies" + i); batchArgs[i] = new BeanPropertySqlParameterSource(user);}int[] c2 = namedParameterJdbcTemplate.batchUpdate(sql, batchArgs);logger.debug("counts = {}", c2);
参考
1.Data access with JDBC
- Spring-JDBC 操作SQL数据库
- 《Spring JDBC 操作数据库》
- Spring JDBC数据库操作类
- Spring使用JDBC操作数据库
- Spring之jdbc数据库操作
- jdbc操作sql server数据库
- JDBC 简介 ,SQL 注入 ,JDBC操作数据库
- spring framwor操作数据库示例spring-jdbc
- Spring集成JDBC操作数据库实例教程
- 用Spring的JDBC直接操作数据库
- spring jdbc-数据库操作对象化模型
- Spring MVC + JDBC 实现数据库操作
- JSP之JDBC操作Sql Server数据库
- JDBC操作SQL Server数据库的步骤
- JSP之JDBC操作Sql Server数据库
- 使用jdbc操作sql server数据库
- JDBC连接数据库&SQL基本操作
- 使用spring jdbc template简化jdbc数据库操作实例代码
- cf#342-D - Finals in arithmetic-构造
- 虚树练习集锦
- 笔记--统一编程接口外观模式
- Jquery学习笔记
- RandomAccessFile用法
- Spring-JDBC 操作SQL数据库
- 理解ThreadLocal
- ios证书过期问题
- hrbust 2147 哈理工oj 经理办公室【水题】
- 张学良-国民党军事失败真相
- jni - c 调用java方法
- 1060. Are They Equal (25)
- linux error
- UVA 11354 - Bond(并查集-按秩合并)