JdbcTemplate 详解一
- JdbcTemplate 入门示例
pom
<dependencies> <!--Spring核心包--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.2.6.RELEASE</version> </dependency> <!--Spring的操作数据库坐标--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.2.6.RELEASE</version> </dependency> <!--Spring测试坐标--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>5.2.6.RELEASE</version> </dependency> <!--Mysql驱动--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.32</version> </dependency> <!--测试包--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> </dependencies>
JdbcTemplate使用很简单,注入一个数据源就可以使用了
public class A001SpringJdbcJdbcTemplateTest { private JdbcTemplate jdbcTemplate; @Before public void init() { DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://localhost:3306/blogsrc?useUnicode=true&characterEncoding=UTF-8"); dataSource.setUsername("root"); dataSource.setPassword("zhao"); jdbcTemplate = new JdbcTemplate(dataSource); } @Test public void queryTest() { String sql = "select * from user"; List<Map<String, Object>> users = jdbcTemplate.queryForList(sql); System.out.println(users); } }
对于参数赋值,可以采用占位符的方式
@Test public void queryByParameterTest() { String sql = "select * from user where id =?"; List<Map<String, Object>> users = jdbcTemplate.queryForList(sql, 1L); List<Map<String, Object>> users1 = jdbcTemplate.queryForList(sql, new Object[] {1L}); }
- mapper映射
Spring JDBC 通过mapper接口把resultSet对象中的数据映射为java对象,例如上述例子中返回 List<Map<String, Object>>
,其实使用的是ColumnMapRowMapper
的mapper实现。我们自己可以通过实现RowMapper
接口的方式自定义从resultSet到java对象的映射关系。
先创建一个table
CREATE TABLE `user` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `password` varchar(255) NOT NULL, `user_name` varchar(255) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
User实体类
public class User implements Serializable { private Long id; private String userName; private String password; // 省略 getter setter }
自定义mapper映射
@Test public void simpleMapperTest() { String sql = "select * from user"; List<User> users = jdbcTemplate.query(sql, new RowMapper<User>() { public User mapRow(ResultSet rs, int rowNum) throws SQLException { User user = new User(); user.setId(rs.getObject("id") == null ? null : rs.getLong("id")); user.setUserName(rs.getString("user_name")); user.setPassword(rs.getString("password")); return user; } }); }
- NamedParameterJdbcTemplate
NamedParameterJdbcTemplate的使用基本上和JdbcTemplate类似,只不过参数的赋值方式由占位符变成了命名参数,命名参数优势在于,如果一个相同的参数出现了多次,只需要进行一次赋值即可。
创建NamedParameterJdbcTemplate对象的两种方式
// 方式1 namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(jdbcTemplate); // 方式2 namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
@Test public void namedParameterJdbcTemplateTest() { String sql = "select * from user where id =:id"; Map<String, Object> parameters = new HashMap<String, Object>(); parameters.put("id", 1L); List<Map<String, Object>> users = namedParameterJdbcTemplate.queryForList(sql, parameters); System.out.println(users); }
- batchUpdate
对于大数据量的数据更新,可以采用batchUpdate接口
@Test public void batchUpdateTest() { String sql = "insert into user (user_name,password) VALUES (?, ?)"; List<User> users = Lists.newArrayList(); for (int i = 0; i <= 10; i++) { User user = new User(); user.setUserName("xiaoming"); user.setPassword("123456"); users.add(user); } jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() { @Override public void setValues(PreparedStatement ps, int i) throws SQLException { User user = users.get(i); int count = 0; ps.setString(++count, user.getUserName());// 索引从1开始 ps.setString(++count, user.getPassword()); } @Override public int getBatchSize() { return users.size(); } }); }
-
与spring整合
只需要注入数据源即可
<!-- 省略dataSource相关配置 --> <!-- 配置 Spirng 的 JdbcTemplate --> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 配置 NamedParameterJdbcTemplate --> <bean id="namedParameterJdbcTemplate" class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate"> <constructor-arg ref="dataSource"></constructor-arg> </bean>
- 创建配置类
SpringConfig.java
package com.day02Jdbc.config; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; /** * @ Author :ShaoWei Sun. * @ Date :Created in 9:25 2018/11/10 */ @Configuration//指定该类是一个配置类、等价于一个spring的配置文件 @ComponentScan(basePackages="com.day02Jdbc")//指定扫包范围 @Import(JdbcConfig.class) //引入JdbcConfig.class文件 public class SpringConfig { }
引入jdbc属性文件
创建Jdbc属性文件 resources/jdbc.properties
jdbc.driverClass=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/mybatis jdbc.username=root jdbc.password=sswqzx
在jdbcConfig中引入jdbc属性资源文件
package com.day02Jdbc.config; import com.alibaba.druid.pool.DruidDataSource; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.PropertySource; import org.springframework.jdbc.core.JdbcTemplate; import javax.sql.DataSource; //import javax.sql.DataSource; /** * @ Author :ShaoWei Sun. * @ Date :Created in 9:28 2018/11/10 */ @PropertySource("classpath:jdbc.properties") public class JdbcConfig { @Value("${jdbc.driverClass}") private String driver; @Value("${jdbc.url}") private String url; @Value("${jdbc.username}") private String user; @Value("${jdbc.password}") private String password; /** * Bean注解:该注解只能写在方法上,表明使用此方法创建一个对象,并且放入spring容器。 * name属性:给当前@Bean注解方法创建的对象指定一个名称(即bean的id)。 * @return */ @Bean(name="dataSource") public DataSource createDataSource(){ DruidDataSource dataSource = new DruidDataSource(); dataSource.setDriverClassName(driver); dataSource.setUrl(url); dataSource.setUsername(user); dataSource.setPassword(password); return dataSource; } @Bean(name="jdbcTemplate") public JdbcTemplate createJdbcTemplate(DataSource dataSource){ return new JdbcTemplate(dataSource); } }
注意:@Bean注解也可以不用指定name,因为基本上都是按照类型注入;如果不指定name,默认是@Bean注解所在的方法的名字。
在SpringConfig中引入JdbcConfig
package com.day02Jdbc.config; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; /** * @ Author :ShaoWei Sun. * @ Date :Created in 9:25 2018/11/10 */ @Configuration//指定该类是一个配置类、等价于一个spring的配置文件 @ComponentScan(basePackages="com.day02Jdbc")//指定扫包范围 @Import(JdbcConfig.class) //引入JdbcConfig.class文件 public class SpringConfig { }
-
springboot整合
@Autowired private JdbcTemplate jdbcTemplate;
项目创建完后,接下来只需要在application.properties中提供数据的基本配置即可,如下:
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource spring.datasource.username=root spring.datasource.password=123 spring.datasource.url=jdbc:mysql:///test01?useUnicode=true&characterEncoding=UTF-8
- 封装工具类
import com.google.common.base.Preconditions; import com.google.common.base.Throwables; import com.google.common.collect.Lists; import com.zxsoft.spider.exception.ServiceException; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.dbutils.BasicRowProcessor; import org.apache.commons.dbutils.RowProcessor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.simple.SimpleJdbcInsert; import org.springframework.stereotype.Repository; import java.util.*; @Repository public class JDBCDao { private static final Logger log = LoggerFactory.getLogger(JDBCDao.class); @Autowired private JdbcTemplate jdbcTemplate; private RowProcessor processor = new BasicRowProcessor(); public <T> List<T> select(String table, String column, Map<String, Object> valueMap, Class<T> clazz) { StringBuilder sql = new StringBuilder("select "); sql.append(column).append(" from ").append(table).append(" where 1=1 "); if (null != valueMap) { Iterator it = valueMap.entrySet().iterator(); while (it.hasNext()) { Map.Entry pair = (Map.Entry) it.next(); sql.append(" and ").append(pair.getKey()).append(" = '").append(pair.getValue()).append("'"); } } log.debug("select sql ==" + sql.toString()); List<T> list = null; try { list = jdbcTemplate.query(sql.toString(), (rs, rowNum) -> processor.toBean(rs, clazz)); } catch (ServiceException e) { log.error(Throwables.getStackTraceAsString(e)); } return list == null ? Lists.newArrayList() : list; } /** * * @param sql * @param clazz * @param <T> * @return */ public <T> List<T> select(String sql, Class<T> clazz) { List<T> list = null; try { list = jdbcTemplate.query(sql, (rs, rowNum) -> processor.toBean(rs, clazz)); } catch (ServiceException e) { log.error(Throwables.getStackTraceAsString(e)); } return list == null ? Lists.newArrayList() : list; } public List<Map<String, Object>> select(String sql) { List<Map<String, Object>> list = null; try { list = jdbcTemplate.queryForList(sql); } catch (ServiceException e) { log.error(Throwables.getStackTraceAsString(e)); } return list == null ? Lists.newArrayList() : list; } public List<Map<String, Object>> select(String sql, Object[] args) { List<Map<String, Object>> list = null; try { list = jdbcTemplate.queryForList(sql, args); } catch (ServiceException e) { log.error(Throwables.getStackTraceAsString(e)); } return list == null ? Lists.newArrayList() : list; } public int queryCount(String table, Map<String, Object> valueMap) { StringBuilder sql = new StringBuilder("select count(1) as count from "); sql.append(table); sql.append(" where 1=1"); Object[] bindArgs = new Object[valueMap.size()]; int i = 0; Iterator it = valueMap.entrySet().iterator(); while (it.hasNext()) { Map.Entry pair = (Map.Entry) it.next(); sql.append(" and ").append(pair.getKey()).append(" = ?"); bindArgs[i] = pair.getValue(); i++; } log.debug("sql ==== " + sql.toString() + " " + Arrays.toString(bindArgs)); return jdbcTemplate.queryForObject(sql.toString(), bindArgs, Integer.class); } /** * 根据表名,字段插入 * * @param tableName * @param valueMap * @return */ public int insert(String tableName, Map<String, Object> valueMap) { Preconditions.checkNotNull(tableName, "table name can not be empty"); Set<String> keySet = valueMap.keySet(); Iterator<String> iterator = keySet.iterator(); StringBuilder columnSql = new StringBuilder(); StringBuilder unknownMarkSql = new StringBuilder(); Object[] bindArgs = new Object[valueMap.size()]; int i = 0; while (iterator.hasNext()) { String key = iterator.next(); columnSql.append(i == 0 ? "" : ","); columnSql.append(key); unknownMarkSql.append(i == 0 ? "" : ","); unknownMarkSql.append("?"); bindArgs[i] = valueMap.get(key); i++; } StringBuilder sql = new StringBuilder(); sql.append("INSERT INTO "); sql.append(tableName); sql.append(" ("); sql.append(columnSql); sql.append(" ) VALUES ("); sql.append(unknownMarkSql); sql.append(" )"); log.debug("insert sql ==== " + sql.toString() + " " + Arrays.toString(bindArgs)); return jdbcTemplate.update(sql.toString(), bindArgs); } /** * 批量插入 * * @param list * @param tableName * @return * @throws Exception */ public int[] batchInsert(String tableName, List<Map<String, Object>> list) throws Exception { if (CollectionUtils.isEmpty(list)) { return new int[1]; } Map<String, Object>[] maps = new Map[list.size()]; for(int i = 0;i< list.size(); i++) { maps[i] = list.get(i); } SimpleJdbcInsert simpleJdbcInsert = new SimpleJdbcInsert(jdbcTemplate); return simpleJdbcInsert.withTableName(tableName).executeBatch(maps); } /** * 根据表名,字段更新 * * @param tableName * @param valueMap * @return */ public int update(String tableName, Map<String, Object> valueMap) { if (valueMap.size() < 1) { return -1; } Set<String> keySet = valueMap.keySet(); Iterator<String> iterator = keySet.iterator(); int i = 0; StringBuilder sql = new StringBuilder(); sql.append("UPDATE "); sql.append(tableName); sql.append(" SET "); Object[] bindArgs = new Object[valueMap.size() - 1]; StringBuilder columnSql = new StringBuilder(); while (iterator.hasNext()) { String key = iterator.next(); if ("id".equals(key.toLowerCase())) { continue; } columnSql.append(i == 0 ? "" : ","); columnSql.append(key + " = ?"); bindArgs[i] = valueMap.get(key); i++; } sql.append(columnSql).append(" WHERE ID = " + valueMap.get("id")); log.debug("update sql ==== " + sql.toString() + " " + Arrays.toString(bindArgs)); return jdbcTemplate.update(sql.toString(), bindArgs); } public int update(String sql, Object[] bindArgs) throws ServiceException { return jdbcTemplate.update(sql, bindArgs); } }
- 表之间的数据导入
public static void main(String[] args) { List<Map<String, Object>> zxCrawlerDbList = zxCrawlerDbJdbcTemplate.queryForList("SELECT * FROM `application_electronic_contract`;"); List<Map<String, Object>> anHuiDbList = anHuiJdbcTemplate.queryForList("SELECT * FROM `application_electronic_contract`;"); Map<String, String> map = new HashMap<>(); for (Map<String, Object> stringObjectMap : anHuiDbList) { String url = stringObjectMap.get("url").toString(); String id = stringObjectMap.get("id").toString(); map.put(url, id); } for (Map<String, Object> objectMap : zxCrawlerDbList) { String url = objectMap.get("url").toString(); if (map.containsKey(url)) { continue; } Iterator<String> iterator = objectMap.keySet().iterator(); while (iterator.hasNext()) {// 循环取键值进行判断 String key = iterator.next();// 键 if (key.startsWith("id")) { iterator.remove();// 移除map中以week字符开头的键对应的键值对 } if (key.startsWith("digest")) { iterator.remove();// 移除map中以lessonNo字符开头的键对应的键值对 } } objectMap.put("type", "3"); objectMap.put("platformCode", "3"); insert("application_electronic_contract", objectMap); } }
故乡明
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话