Springboot2中常见的数据库访问方法详解
作者:杰西笔记
前言
在现代 Java 企业级开发中,Spring Boot 已成为构建微服务和 Web 应用的主流框架。其“约定优于配置”的设计理念极大地简化了项目搭建与维护成本。而在实际开发过程中,数据库操作 是绝大多数应用的核心功能之一。本文将围绕 Spring Boot 2 版本(以 2.7.x 为主),深入讲解如何进行高效、稳定的数据库访问,涵盖多种主流技术栈,并结合实际案例,帮助开发者全面掌握 Spring Boot 中的数据持久化方案。
一、使用 Spring Data JPA 实现 ORM 操作
1.1 什么是 JPA
JPA(Java Persistence API)是 Java EE 中定义的一套持久化规范,它并不直接操作数据库,而是由具体的实现(如 Hibernate、EclipseLink)来完成底层工作。Spring Data JPA 是 Spring 对 JPA 规范的进一步封装,提供了更简洁的 API 和自动化的 CRUD 支持。
适用场景:快速开发、中小型项目、注重实体建模而非 SQL 控制的系统。
1.2 添加依赖并启用 JPA
首先,在 pom.xml 文件中引入必要的依赖:
<dependencies>
<!-- Spring Data JPA 起步依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- MySQL 驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- Web 起步依赖(用于测试接口) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
Spring Boot 会自动配置以下核心组件:
EntityManagerFactory:JPA 核心工厂,负责创建实体管理器。PlatformTransactionManager:事务管理器,支持声明式事务。DataSource:数据源对象。JpaRepositoriesAutoConfiguration:自动扫描并注册 Repository 接口。
1.3 配置数据库连接信息
在 application.yml 中配置 MySQL 数据源及 JPA 行为:
spring:
datasource:
url: jdbc:mysql://localhost:3306/springboot_db?useSSL=false&serverTimezone=UTC&characterEncoding=utf8
username: root
password: yourpassword
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
hibernate:
ddl-auto: update # 自动建表策略
show-sql: true # 控制台输出 SQL
properties:
hibernate:
format_sql: true # 格式化 SQL 输出
dialect: org.hibernate.dialect.MySQL8Dialect # 指定方言
open-in-view: false # 防止 N+1 查询问题
参数说明:
ddl-auto:
none:不做任何处理validate:验证表结构是否匹配update:更新表结构(推荐开发环境)create:每次启动都重建表(慎用)create-drop:启动时创建,关闭时删除
生产环境建议设置为 none,通过 Flyway 或 Liquibase 管理数据库版本。
1.4 定义实体类(Entity)
创建一个用户实体类,映射到数据库表 user:
import javax.persistence.*;
@Entity
@Table(name = "user")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "name", length = 50, nullable = false)
private String name;
@Column(name = "age")
private Integer age;
@Column(name = "email", unique = true)
private String email;
// 构造方法
public User() {}
public User(String name, Integer age, String email) {
this.name = name;
this.age = age;
this.email = email;
}
// Getter 和 Setter 方法省略...
}
1.5 创建 Repository 接口
Spring Data JPA 的强大之处在于只需定义接口,无需编写实现类即可完成 CRUD 操作。
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
// 根据姓名查询(方法名解析)
List<User> findByName(String name);
// 根据姓名和年龄查询
List<User> findByNameAndAge(String name, Integer age);
// 模糊查询
List<User> findByNameContaining(String keyword);
// 使用 @Query 注解自定义 SQL
@Query("SELECT u FROM User u WHERE u.age > :age")
List<User> findByAgeGreaterThan(@Param("age") Integer age);
}
方法名解析机制:Spring Data JPA 支持通过方法名自动生成查询语句,如 findByXxxAndYyy、findByXxxOrderByYyyDesc 等。
1.6 编写 Service 层逻辑
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Optional;
@Service
@Transactional
public class UserService {
@Autowired
private UserRepository userRepository;
public List<User> findAll() {
return userRepository.findAll();
}
public User findById(Long id) {
Optional<User> user = userRepository.findById(id);
return user.orElse(null);
}
public User save(User user) {
return userRepository.save(user);
}
public void deleteById(Long id) {
userRepository.deleteById(id);
}
public List<User> searchByName(String name) {
return userRepository.findByNameContaining(name);
}
}
1.7 控制器层暴露接口
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserService userService;
@GetMapping
public List<User> getAll() {
return userService.findAll();
}
@GetMapping("/{id}")
public User getById(@PathVariable Long id) {
return userService.findById(id);
}
@PostMapping
public User create(@RequestBody User user) {
return userService.save(user);
}
@PutMapping("/{id}")
public User update(@PathVariable Long id, @RequestBody User user) {
user.setId(id);
return userService.save(user);
}
@DeleteMapping("/{id}")
public void delete(@PathVariable Long id) {
userService.deleteById(id);
}
}
1.8 测试验证
启动应用后,可通过 Postman 或 curl 测试:
curl -X POST http://localhost:8080/api/users \
-H "Content-Type: application/json" \
-d '{"name":"张三","age":25,"email":"zhangsan@example.com"}'
查看控制台输出的 SQL 是否正常执行。
二、集成 Druid 数据源提升性能与监控能力
虽然 Spring Boot 默认使用 HikariCP 作为连接池,但在国内企业级项目中,Druid 因其强大的监控功能和稳定性被广泛采用。
2.1 引入 Druid 依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.11</version>
</dependency>
2.2 配置 Druid 数据源
修改 application.yml:
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
# 基础连接属性
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/springboot_db?useSSL=false&serverTimezone=UTC
username: root
password: yourpassword
# 连接池配置
initial-size: 5
min-idle: 5
max-active: 20
max-wait: 60000
time-between-eviction-runs-millis: 60000
min-evictable-idle-time-millis: 300000
validation-query: SELECT 1
test-while-idle: true
test-on-borrow: false
test-on-return: false
# 打开 PSCache,并指定每个连接上 PSCache 的大小
pool-prepared-statements: true
max-pool-prepared-statement-per-connection-size: 20
# 配置监控统计拦截的 filters
filters: stat,wall,log4j
# SQL 防火墙和慢 SQL 记录
connection-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
2.3 配置监控页面(StatViewServlet)
创建配置类启用 Druid 监控:
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class DruidConfig {
@Bean
@ConfigurationProperties("spring.datasource.druid")
public DataSource dataSource() {
return DruidDataSourceBuilder.create().build();
}
@Bean
public ServletRegistrationBean<StatViewServlet> statViewServlet() {
StatViewServlet servlet = new StatViewServlet();
ServletRegistrationBean<StatViewServlet> bean = new ServletRegistrationBean<>(servlet, "/druid/*");
Map<String, String> initParams = new HashMap<>();
initParams.put("loginUsername", "admin");
initParams.put("loginPassword", "123456");
initParams.put("allow", ""); // 允许所有人访问
initParams.put("deny", "192.168.1.1"); // 拒绝特定 IP
bean.setInitParameters(initParams);
return bean;
}
@Bean
public FilterRegistrationBean<WebStatFilter> webStatFilter() {
WebStatFilter filter = new WebStatFilter();
FilterRegistrationBean<WebStatFilter> bean = new FilterRegistrationBean<>(filter);
bean.setUrlPatterns(Arrays.asList("/*"));
bean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
return bean;
}
}
访问 http://localhost:8080/druid 即可进入监控页面,查看:
- SQL 执行次数、耗时
- 连接池状态
- 慢 SQL 日志
- Web 请求统计
三、使用 MyBatis 进行灵活 SQL 控制
当业务逻辑复杂、需要精细控制 SQL 时,MyBatis 是更合适的选择。
3.1 添加依赖
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.3.1</version>
</dependency>
3.2 配置 MyBatis
mybatis:
mapper-locations: classpath:mapping/*.xml
type-aliases-package: com.example.entity
configuration:
map-underscore-to-camel-case: true # 开启驼峰映射
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 控制台打印 SQL
3.3 编写 Mapper 接口与 XML 映射文件
接口:
@Mapper
public interface UserMapper {
List<User> findAll();
User findById(Long id);
int insert(User user);
int update(User user);
int deleteById(Long id);
}
XML 文件(src/main/resources/mapping/UserMapper.xml):
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mapper.UserMapper">
<resultMap id="BaseResultMap" type="com.example.entity.User">
<id property="id" column="id"/>
<result property="name" column="name"/>
<result property="age" column="age"/>
<result property="email" column="email"/>
</resultMap>
<select id="findAll" resultMap="BaseResultMap">
SELECT * FROM user
</select>
<select id="findById" parameterType="long" resultMap="BaseResultMap">
SELECT * FROM user WHERE id = #{id}
</select>
<insert id="insert" parameterType="com.example.entity.User" useGeneratedKeys="true" keyProperty="id">
INSERT INTO user(name, age, email) VALUES (#{name}, #{age}, #{email})
</insert>
<update id="update" parameterType="com.example.entity.User">
UPDATE user SET name=#{name}, age=#{age}, email=#{email} WHERE id=#{id}
</update>
<delete id="deleteById" parameterType="long">
DELETE FROM user WHERE id = #{id}
</delete>
</mapper>
3.4 使用注解方式(可选)
对于简单 SQL,可以直接使用注解:
@Mapper
public interface UserMapper {
@Select("SELECT * FROM user WHERE id = #{id}")
User findById(@Param("id") Long id);
@Insert("INSERT INTO user(name, age, email) VALUES (#{name}, #{age}, #{email})")
@Options(useGeneratedKeys = true, keyProperty = "id")
int insert(User user);
}
四、整合 MyBatis-Plus 提升开发效率
MyBatis-Plus 是 MyBatis 的增强工具,提供了通用 CRUD、分页、代码生成等功能,极大提升开发效率。
4.1 添加依赖
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3.1</version>
</dependency>
4.2 配置插件(分页支持)
@Configuration
@MapperScan("com.example.mapper")
public class MyBatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 添加分页插件
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
4.3 定义实体与 Mapper
@Data
@TableName("user")
public class User {
@TableId(type = IdType.AUTO)
private Long id;
private String name;
private Integer age;
private String email;
}
@Mapper
public interface UserMapper extends BaseMapper<User> {
}
4.4 使用内置方法完成 CRUD
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
public List<User> listAll() {
return userMapper.selectList(null);
}
public IPage<User> page(int pageNum, int pageSize) {
Page<User> page = new Page<>(pageNum, pageSize);
return userMapper.selectPage(page, null);
}
public List<User> searchByName(String name) {
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.like("name", name);
return userMapper.selectList(wrapper);
}
}
4.5 条件构造器(QueryWrapper)
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.gt("age", 18)
.like("name", "王")
.orderByDesc("id");
List<User> users = userMapper.selectList(wrapper);
五、其他数据库访问方式简述
| 方式 | 特点 |
|---|---|
| JdbcTemplate | 轻量级,适合简单 SQL,需手动映射结果 |
| Spring Data JDBC | 轻量 ORM,比 JPA 简单,适合简单对象映射 |
| R2DBC | 响应式数据库连接,适用于 WebFlux 架构 |
六、总结与选型建议
| 技术 | 优点 | 缺点 | 推荐场景 |
|---|---|---|---|
| JPA | 快速开发,自动 CRUD | SQL 控制弱,学习曲线陡 | 中小型项目、快速原型 |
| MyBatis | SQL 灵活,易于优化 | 需写 XML,维护成本高 | 复杂查询、遗留系统 |
| MyBatis-Plus | 开发效率极高,功能丰富 | 对新手有一定门槛 | 推荐首选,尤其互联网项目 |
| JdbcTemplate | 轻量、直接 | 无 ORM,编码繁琐 | 简单脚本、工具类 |
| Druid | 监控能力强,稳定 | 配置较复杂 | 所有生产环境推荐集成 |
最终建议:
- 若追求开发效率与功能完整性,推荐 MyBatis-Plus + Druid
- 若团队熟悉 JPA 且项目偏重领域模型,可选择 Spring Data JPA
- 若为高并发响应式系统,则考虑 R2DBC
通过本文的详细讲解,相信你已经掌握了 Spring Boot 2 中各种数据库操作方式的核心要点。在实际项目中,合理选择技术栈,结合业务需求,才能构建出高性能、易维护的应用系统。
以上就是Springboot2中常见的数据库访问方法详解的详细内容,更多关于Springboot数据库访问的资料请关注脚本之家其它相关文章!
