在现代 Java 应用开发中,数据持久化层是非常重要的组成部分。Spring Boot 3 和 Spring Data JPA 的结合为我们提供了一个简洁、高效的解决方案,可以快速实现数据访问层逻辑,减少冗余代码。本文将详细介绍如何在 Spring Boot 3 中集成 Spring Data JPA,并展示一些常见的用法和最佳实践。
Spring Data JPA 是 Spring 提供的一个模块,基于 Java Persistence API (JPA) 规范,简化了数据访问层的开发。通过它,我们可以通过少量的配置和代码完成大多数的数据持久化操作。它帮助我们避免了繁琐的 DAO 层代码,实现了一种声明式的数据访问方式。
Spring Data JPA 能够自动生成常见的增删改查方法,并提供了强大的查询生成机制,允许根据方法名自动生成 SQL 语句。
JPA 中的实体是与数据库表对应的 Java 类。每个实体对象都代表数据库表中的一行记录,实体中的每个字段对应表中的一列。
package com.coderjia.boot315shardingsphere.bean;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.Data;
@Data
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false, unique = true)
private String username;
@Column(nullable = false)
private String password;
}
Spring Data JPA 中的 Repository
是一个接口层,它通过接口方法帮助我们简化与数据库的交互。JpaRepository
是 Spring Data JPA 提供的最重要的接口之一,它包含了常用的 CRUD 操作,并且可以通过命名规则实现动态查询。
public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByUsername(String username);
}
JpaRepository
继承了哪些接口?
CrudRepository
:提供基础的增删改查方法(save
, findById
, delete
等)。PagingAndSortingRepository
:提供分页和排序功能。QueryByExampleExecutor
:提供查询范例(Query by Example)的能力。Spring Data JPA 根据方法名称自动生成查询。比如 findByUsername
将自动生成类似于 SELECT * FROM users WHERE username = ?
的 SQL 语句。开发者只需定义方法名称,无需手动编写 SQL。
首先,在 Spring Boot 3 项目中,需要引入 spring-boot-starter-data-jpa
依赖,同时配置数据库驱动依赖。例如,使用 MySQL 的话,可以这样配置:
<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>
</dependencies>
在 application.yml
中配置数据库连接:
JPA 可用配置项见 org.springframework.boot.autoconfigure.orm.jpa.JpaProperties
spring:
application:
name: spring-boot3-15-shardingsphere
datasource:
url: jdbc:mysql://localhost:3306/master_db?useSSL=false&serverTimezone=UTC
username: root
password: root123
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
database-platform: org.hibernate.dialect.MySQL8Dialect
generateDdl: true # 自动更新数据库表结构
show-sql: true # 是否显示 SQL 语句
接下来,我们创建一个简单的 User
实体:
package com.coderjia.boot315shardingsphere.bean;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.Data;
/**
* @author CoderJia
* @create 2024/10/14 下午 07:52
* @Description
**/
@Data
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false, unique = true)
private String username;
@Column(nullable = false)
private String password;
}
接着,我们为 User
实体创建一个 UserRepository
接口,继承 JpaRepository
,它会自动为我们生成常见的增删改查方法。
package com.coderjia.boot315shardingsphere.dao;
import com.coderjia.boot315shardingsphere.bean.User;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.Optional;
/**
* @author CoderJia
* @create 2024/10/14 下午 07:54
* @Description
**/
public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByUsername(String username);
}
服务层封装了业务逻辑,依赖于 UserRepository
实现用户相关的操作。
package com.coderjia.boot315shardingsphere.service;
import com.coderjia.boot315shardingsphere.bean.User;
import com.coderjia.boot315shardingsphere.dao.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
/**
* @author CoderJia
* @create 2024/10/14 下午 07:56
* @Description
**/
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
public User createUser(User user) {
return userRepository.save(user);
}
public Optional<User> getUserByUsername(String username) {
return userRepository.findByUsername(username);
}
public List<User> getAllUsers() {
return userRepository.findAll();
}
public void deleteUser(Long id) {
userRepository.deleteById(id);
}
}
控制器层暴露了 REST API 接口,用户可以通过这些接口与应用进行交互。
package com.coderjia.boot315shardingsphere.controller;
import com.coderjia.boot315shardingsphere.bean.User;
import com.coderjia.boot315shardingsphere.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* @author CoderJia
* @create 2024/10/14 下午 07:57
* @Description
**/
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserService userService;
@PostMapping
public User createUser(@RequestBody User user) {
return userService.createUser(user);
}
@GetMapping("/{username}")
public ResponseEntity<User> getUserByUsername(@PathVariable("username") String username) {
return userService.getUserByUsername(username)
.map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build());
}
@GetMapping
public List<User> getAllUsers() {
return userService.getAllUsers();
}
@DeleteMapping("/{id}")
public void deleteUser(@PathVariable("id") Long id) {
userService.deleteUser(id);
}
}
至此,我们已经完成了 Spring Boot 3 集成 Spring Data JPA 的基本配置和功能实现。运行应用后,Spring Data JPA 会自动创建数据库表,并处理数据库的 CRUD 操作。
除了基本的增删改查功能,Spring Data JPA 还提供了许多高级功能,例如分页、排序和自定义查询。
Spring Data JPA 提供了分页与排序的功能,利用 Pageable
接口,我们可以轻松实现数据的分页查询。
public Page<User> getUsersPaged(Pageable pageable) {
return userRepository.findAll(pageable);
}
在控制器中使用分页查询时,可以通过请求参数传递分页信息:
@GetMapping("/paged")
public Page<User> getUsersPaged(@RequestParam("page") int page, @RequestParam("size") int size) {
Pageable pageable = PageRequest.of(page, size);
return userService.getUsersPaged(pageable);
}
除了通过方法名称生成查询,Spring Data JPA 还允许我们使用 @Query
注解编写自定义的 JPQL 或原生 SQL 查询。
public interface UserRepository extends JpaRepository<User, Long> {
@Query("SELECT u FROM User u WHERE u.username = ?1")
Optional<User> findUserByUsername(String username);
}
通过 Spring Data JPA,可以使用 JPA 提供的乐观锁和悲观锁机制,确保在并发环境下的数据一致性。
@Data
@Entity
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private Integer stock;
@Version
private Integer version; // 乐观锁版本字段
}
创建 ProductRepository
import org.springframework.data.jpa.repository.JpaRepository;
public interface ProductRepository extends JpaRepository<Product, Long> {
}
创建 ProductService
import jakarta.persistence.OptimisticLockException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class ProductService {
@Autowired
private ProductRepository productRepository;
public void updateProductStock(Long productId, int quantity) {
try {
Product product = productRepository.findById(productId).orElseThrow();
product.setStock(product.getStock() - quantity);
productRepository.save(product); // 触发乐观锁机制
} catch (OptimisticLockException e) {
System.out.println("OptimisticLockException: Data has been modified by another transaction.");
}
}
}
测试乐观锁
@SpringBootTest
class OptimisticLockTest {
@Autowired
private ProductService productService;
@Test
void testOptimisticLocking() throws InterruptedException {
// 启动两个线程同时修改同一条记录
Thread thread1 = new Thread(() -> productService.updateProductStock(1L, 1));
Thread thread2 = new Thread(() -> productService.updateProductStock(1L, 1));
thread1.start();
thread2.start();
thread1.join();
thread2.join();
}
}
Spring Boot 3 + Spring Data JPA 提供了一个强大且易用的数据访问层解决方案。它大大减少了数据访问层的样板代码,使我们能够专注于业务逻辑的开发。通过 JPA 的实体映射、动态查询、分页排序、乐观锁等特性,我们可以非常高效地开发应用程序。
集成 Spring Data JPA 后,我们可以快速上手,构建面向数据库的应用程序,同时保留灵活的扩展能力和强大的功能支持。
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有