您好,登录后才能下订单哦!
密码登录
登录注册
点击 登录注册 即表示同意《亿速云用户服务条款》
# SpringBoot 中怎么利用JdbcTemplate操作数据库
## 一、JdbcTemplate 概述
### 1.1 什么是 JdbcTemplate
JdbcTemplate 是 Spring 框架提供的一个核心 JDBC 工具类,它封装了原生 JDBC API 的复杂操作,提供了更简洁的数据库访问方式。主要特点包括:
- 自动管理资源(Connection/Statement/ResultSet)
- 简化异常处理(将检查异常转换为运行时异常)
- 提供丰富的 CRUD 操作方法
- 支持命名参数和预编译语句
### 1.2 与 MyBatis/JPA 的对比
| 特性 | JdbcTemplate | MyBatis | JPA/Hibernate |
|--------------|--------------------|--------------------|--------------------|
| 学习曲线 | 低 | 中 | 高 |
| 灵活性 | 极高 | 高 | 中 |
| 自动化程度 | 低(手动写SQL) | 中(XML/注解) | 高(自动生成SQL) |
| 适用场景 | 简单CRUD/复杂SQL | 复杂SQL映射 | 对象关系映射 |
## 二、SpringBoot 集成 JdbcTemplate
### 2.1 添加依赖
在 `pom.xml` 中添加 starter 和数据库驱动:
```xml
<dependencies>
<!-- Spring Boot JDBC starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- 数据库驱动(以MySQL为例) -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
</dependencies>
application.yml
配置示例:
spring:
datasource:
url: jdbc:mysql://localhost:3306/test_db?useSSL=false&serverTimezone=UTC
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
# HikariCP 连接池配置(默认)
hikari:
maximum-pool-size: 10
minimum-idle: 5
connection-timeout: 30000
通过构造器注入:
@Repository
public class UserDaoImpl implements UserDao {
private final JdbcTemplate jdbcTemplate;
@Autowired
public UserDaoImpl(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
}
public int insert(User user) {
String sql = "INSERT INTO user(name, age, email) VALUES(?, ?, ?)";
return jdbcTemplate.update(
sql,
user.getName(),
user.getAge(),
user.getEmail()
);
}
// 批量插入
public int[] batchInsert(List<User> users) {
String sql = "INSERT INTO user(name, age, email) VALUES(?, ?, ?)";
return jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
@Override
public void setValues(PreparedStatement ps, int i) throws SQLException {
User user = users.get(i);
ps.setString(1, user.getName());
ps.setInt(2, user.getAge());
ps.setString(3, user.getEmail());
}
@Override
public int getBatchSize() {
return users.size();
}
});
}
public User getById(Long id) {
String sql = "SELECT * FROM user WHERE id = ?";
return jdbcTemplate.queryForObject(sql, new Object[]{id}, (rs, rowNum) -> {
User user = new User();
user.setId(rs.getLong("id"));
user.setName(rs.getString("name"));
user.setAge(rs.getInt("age"));
user.setEmail(rs.getString("email"));
return user;
});
}
public List<User> listAll() {
String sql = "SELECT * FROM user";
return jdbcTemplate.query(sql, (rs, rowNum) -> {
User user = new User();
user.setId(rs.getLong("id"));
// 其他字段设置...
return user;
});
}
public int countUsers() {
String sql = "SELECT COUNT(*) FROM user";
return jdbcTemplate.queryForObject(sql, Integer.class);
}
// 更新
public int update(User user) {
String sql = "UPDATE user SET name=?, age=?, email=? WHERE id=?";
return jdbcTemplate.update(
sql,
user.getName(),
user.getAge(),
user.getEmail(),
user.getId()
);
}
// 删除
public int delete(Long id) {
String sql = "DELETE FROM user WHERE id=?";
return jdbcTemplate.update(sql, id);
}
使用 NamedParameterJdbcTemplate
:
@Autowired
private NamedParameterJdbcTemplate namedJdbcTemplate;
public User getByName(String name) {
String sql = "SELECT * FROM user WHERE name = :name";
Map<String, Object> params = new HashMap<>();
params.put("name", name);
return namedJdbcTemplate.queryForObject(sql, params, (rs, rowNum) -> {
// 对象映射...
});
}
public void callProcedure() {
jdbcTemplate.execute("{call update_user_status(?, ?)}",
(CallableStatementCallback<Void>) cs -> {
cs.setLong(1, 1001L);
cs.registerOutParameter(2, Types.INTEGER);
cs.execute();
log.info("Out parameter: {}", cs.getInt(2));
return null;
});
}
在 Service 层添加 @Transactional
:
@Service
@Transactional
public class UserService {
@Autowired
private UserDao userDao;
public void transferBalance(Long fromId, Long toId, BigDecimal amount) {
userDao.deductBalance(fromId, amount);
// 模拟业务异常
if (amount.compareTo(BigDecimal.ZERO) < 0) {
throw new IllegalArgumentException("金额不能为负");
}
userDao.addBalance(toId, amount);
}
}
sql.properties
或常量类)StringBuilder
或 JOOQ// 1. 使用预编译语句
jdbcTemplate.setFetchSize(100); // 设置批量获取大小
// 2. 结果集处理优化
jdbcTemplate.query(sql, new ResultSetExtractor<List<User>>() {
@Override
public List<User> extractData(ResultSet rs) throws SQLException {
// 自定义高效处理逻辑
}
});
// 3. 连接池配置
spring.datasource.hikari.maximum-pool-size=20
try {
jdbcTemplate.update("INSERT...");
} catch (DuplicateKeyException e) {
// 处理唯一键冲突
} catch (DataAccessException e) {
// 处理其他数据库异常
}
@Repository
public class UserDaoImpl implements UserDao {
private static final String INSERT_SQL = "INSERT...";
private static final String SELECT_BY_ID_SQL = "SELECT...";
private final JdbcTemplate jdbcTemplate;
@Override
public List<User> findByAgeGreaterThan(int age) {
return jdbcTemplate.query(
"SELECT * FROM user WHERE age > ? ORDER BY name",
new BeanPropertyRowMapper<>(User.class),
age
);
}
}
@SpringBootTest
class UserDaoTest {
@Autowired
private UserDao userDao;
@Test
@Transactional // 测试后自动回滚
void testInsert() {
User user = new User("test", 25, "test@example.com");
int affected = userDao.insert(user);
assertEquals(1, affected);
}
}
JdbcTemplate 在 SpringBoot 中的优势: - 轻量级,无额外学习成本 - 适合简单CRUD和存储过程调用 - 与 Spring 生态完美集成
适用场景建议: - 小型项目或微服务中的简单数据访问 - 需要执行原生SQL的复杂查询 - 与其他ORM框架混合使用 “`
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。