java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Springboot数据库访问

Springboot2中常见的数据库访问方法详解

作者:杰西笔记

在现代 Java 企业级开发中,Spring Boot 已成为构建微服务和 Web 应用的主流框架,本文将围绕 Spring Boot 2 版本深入讲解如何进行高效,稳定的数据库访问,希望对大家有所帮助

前言

在现代 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 会自动配置以下核心组件:

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,通过 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 支持通过方法名自动生成查询语句,如 findByXxxAndYyyfindByXxxOrderByYyyDesc 等。

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 即可进入监控页面,查看:

三、使用 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快速开发,自动 CRUDSQL 控制弱,学习曲线陡中小型项目、快速原型
MyBatisSQL 灵活,易于优化需写 XML,维护成本高复杂查询、遗留系统
MyBatis-Plus开发效率极高,功能丰富对新手有一定门槛推荐首选,尤其互联网项目
JdbcTemplate轻量、直接无 ORM,编码繁琐简单脚本、工具类
Druid监控能力强,稳定配置较复杂所有生产环境推荐集成

最终建议

通过本文的详细讲解,相信你已经掌握了 Spring Boot 2 中各种数据库操作方式的核心要点。在实际项目中,合理选择技术栈,结合业务需求,才能构建出高性能、易维护的应用系统。

以上就是Springboot2中常见的数据库访问方法详解的详细内容,更多关于Springboot数据库访问的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文