Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >重学SpringBoot3-Spring Data JPA

重学SpringBoot3-Spring Data JPA

作者头像
CoderJia
发布于 2024-10-18 01:24:35
发布于 2024-10-18 01:24:35
43100
代码可运行
举报
运行总次数:0
代码可运行

在现代 Java 应用开发中,数据持久化层是非常重要的组成部分。Spring Boot 3 和 Spring Data JPA 的结合为我们提供了一个简洁、高效的解决方案,可以快速实现数据访问层逻辑,减少冗余代码。本文将详细介绍如何在 Spring Boot 3 中集成 Spring Data JPA,并展示一些常见的用法和最佳实践。

1. 什么是 Spring Data JPA?

Spring Data JPA 是 Spring 提供的一个模块,基于 Java Persistence API (JPA) 规范,简化了数据访问层的开发。通过它,我们可以通过少量的配置和代码完成大多数的数据持久化操作。它帮助我们避免了繁琐的 DAO 层代码,实现了一种声明式的数据访问方式。

Spring Data JPA 能够自动生成常见的增删改查方法,并提供了强大的查询生成机制,允许根据方法名自动生成 SQL 语句。

2. Spring Data JPA 的核心概念

2.1. 实体(Entity)

JPA 中的实体是与数据库表对应的 Java 类。每个实体对象都代表数据库表中的一行记录,实体中的每个字段对应表中的一列。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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;
}

2.2. Repository(仓库)

Spring Data JPA 中的 Repository 是一个接口层,它通过接口方法帮助我们简化与数据库的交互。JpaRepository 是 Spring Data JPA 提供的最重要的接口之一,它包含了常用的 CRUD 操作,并且可以通过命名规则实现动态查询。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public interface UserRepository extends JpaRepository<User, Long> {
    Optional<User> findByUsername(String username);
}

JpaRepository 继承了哪些接口?

  • CrudRepository:提供基础的增删改查方法(save, findById, delete 等)。
  • PagingAndSortingRepository:提供分页和排序功能。
  • QueryByExampleExecutor:提供查询范例(Query by Example)的能力。

2.3. 查询生成策略

Spring Data JPA 根据方法名称自动生成查询。比如 findByUsername 将自动生成类似于 SELECT * FROM users WHERE username = ? 的 SQL 语句。开发者只需定义方法名称,无需手动编写 SQL。

3. Spring Boot 3 集成 Spring Data JPA

3.1. 引入依赖

首先,在 Spring Boot 3 项目中,需要引入 spring-boot-starter-data-jpa 依赖,同时配置数据库驱动依赖。例如,使用 MySQL 的话,可以这样配置:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<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>

3.2. 数据源配置

application.yml 中配置数据库连接:

JPA 可用配置项见 org.springframework.boot.autoconfigure.orm.jpa.JpaProperties

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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 语句

3.3. 创建实体类

接下来,我们创建一个简单的 User 实体:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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;
}

3.4. 创建 Repository 接口

接着,我们为 User 实体创建一个 UserRepository 接口,继承 JpaRepository,它会自动为我们生成常见的增删改查方法。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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);
}

3.5. 编写服务层

服务层封装了业务逻辑,依赖于 UserRepository 实现用户相关的操作。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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);
    }
    
}

3.6. 编写控制器

控制器层暴露了 REST API 接口,用户可以通过这些接口与应用进行交互。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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);
    }
}

3.7. 运行应用

至此,我们已经完成了 Spring Boot 3 集成 Spring Data JPA 的基本配置和功能实现。运行应用后,Spring Data JPA 会自动创建数据库表,并处理数据库的 CRUD 操作。

自动创建数据库表
自动创建数据库表

3.8. 测试

3.8.1 新增用户

新增
新增

3.8.2 查询用户

查询
查询

3.8.3 查询所有

查询所有
查询所有

3.8.4 删除用户

删除
删除

4. 高级功能

除了基本的增删改查功能,Spring Data JPA 还提供了许多高级功能,例如分页、排序和自定义查询。

4.1. 分页与排序

Spring Data JPA 提供了分页与排序的功能,利用 Pageable 接口,我们可以轻松实现数据的分页查询。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    public Page<User> getUsersPaged(Pageable pageable) {
        return userRepository.findAll(pageable);
    }

在控制器中使用分页查询时,可以通过请求参数传递分页信息:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    @GetMapping("/paged")
    public Page<User> getUsersPaged(@RequestParam("page") int page, @RequestParam("size") int size) {
        Pageable pageable = PageRequest.of(page, size);
        return userService.getUsersPaged(pageable);
    }
分页
分页

4.2. 自定义查询

除了通过方法名称生成查询,Spring Data JPA 还允许我们使用 @Query 注解编写自定义的 JPQL 或原生 SQL 查询。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public interface UserRepository extends JpaRepository<User, Long> {

    @Query("SELECT u FROM User u WHERE u.username = ?1")
    Optional<User> findUserByUsername(String username);
}

4.3. 乐观锁与悲观锁

通过 Spring Data JPA,可以使用 JPA 提供的乐观锁和悲观锁机制,确保在并发环境下的数据一致性

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Data
@Entity
public class Product {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;
    private Integer stock;

    @Version
    private Integer version;  // 乐观锁版本字段
}

创建 ProductRepository

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import org.springframework.data.jpa.repository.JpaRepository;

public interface ProductRepository extends JpaRepository<Product, Long> {
}

创建 ProductService

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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.");
        }
    }
}

测试乐观锁

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@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();
    }
}
测试乐观锁
测试乐观锁

5. 总结

Spring Boot 3 + Spring Data JPA 提供了一个强大且易用的数据访问层解决方案。它大大减少了数据访问层的样板代码,使我们能够专注于业务逻辑的开发。通过 JPA 的实体映射、动态查询、分页排序、乐观锁等特性,我们可以非常高效地开发应用程序。

集成 Spring Data JPA 后,我们可以快速上手,构建面向数据库的应用程序,同时保留灵活的扩展能力和强大的功能支持。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-10-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Redis最基础内容
String类型,也就是字符串类型,是Redis中最简单的存储类型。其value是字符串,不过根据字符串的格式不同,又可以分为3类:
ha_lydms
2023/08/10
2491
Redis最基础内容
深入Redis数据结构和底层原理
其中一个重要的原因,就是Redis中高效的数据结构,因此我们就专门的来研究下Redis的核心数据结构,Go!
闫同学
2022/10/31
3590
深入Redis数据结构和底层原理
Redis 数据类型
string是redis最基本的类型,一个key对应一个value string类型是二进制安全的,即它可以包含任何数据
全栈程序员站长
2022/07/25
3300
常用五大数据类型
命令大小写都可以,如果你只想单纯看 API,不想看例子,请移到最下面的 指令总结。
用户9615083
2022/12/25
8470
常用五大数据类型
redis缓存数据库
redis 介绍 redis是业界主流的key-value nosql 数据库之一。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是r
用户1679793
2018/07/05
4.5K0
Redis 数据类型
Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。
子润先生
2021/07/05
5130
Redis 数据类型
Redis00--Redis的基本命令
Redis hash 是一个键值对集合,Redis hash是一个String类型的field和value的映射表,hash特别适合存储对象,例如SpringSession中的session信息,存储用户信息,用户主页访问量等等。
码农飞哥
2021/08/18
3590
Redis-1.Redis数据结构
自增自减命令 自增自减命令只能作用于整数,如果对不存在的键或者保存了空串的键执行自增/自减操作,那么会将这个键的值当作0处理,如果对无法解释为整数或者浮点数的字符串值性自增/自减操作,把额会返回一个错误。
悠扬前奏
2019/05/30
7110
Redis笔记(二):Redis数据类型
Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。
朝雨忆轻尘
2019/06/19
6240
Redis常用命令、5种数据类型的内部编码实现以及实用场景
相信绝大部分人,应该是99%的人都知道Redis的5种的基本类型、它们分别是:字符串、哈希、列表、集合、有序集合,就如同下图这样:
Java学习录
2019/05/06
5120
Redis常用命令、5种数据类型的内部编码实现以及实用场景
简简单单入个Redis的门
Redis是一种key-value的存储系统,它是一种nosql(Not Only [SQL])非关系型的数据库,它支持string(字符串)、list(链表)、set(集合)、hash(哈希类型)和zset(sorted set --有序集合)数据类型,这些数据类型有着丰富的操作,且均具有原子性。
code随笔
2020/11/06
3770
Redis 简介
REmote DIctionary Server(Redis) 是一个由 Salvatore Sanfilippo 开发的 key-value 存储系统。
acc8226
2022/05/17
3380
Redis 简介
Redis常用命令
推荐这个可视化工具,GitHub地址:https://github.com/qishibo/AnotherRedisDesktopManager/
乐心湖
2021/01/18
8510
Redis常用命令
一文读懂Redis数据类型
也就是说redis的存储类型 key(string) -- value(string、hash、list、set、zet)
Devops海洋的渔夫
2022/01/17
4290
一文读懂Redis数据类型
Redis相关命令
什么是Redis   Redis首先是一个存储数据库,数据在缓存在内存中,数据是K-V结构。 Redis的使用 Redis安装使用 Redis的数据类型 类型 描述 备注 string 字符串 K-V 最大值存储512M list 简单字符串列表,可以将元素添加最左边或者右边 最多存储232 - 1 set string类型的无序集合 Hash表实现,查询效率O(1),最多存储232 - 1 zset 有序集合,成员不能重复,但是scope可以重复 image.png hash 键值对的集合 image.p
OPice
2020/01/15
8040
redis基础指令及数据类型
全局指令 redis有5种数据类型,它们是键值对中的值,对于键来说有些通用的命令。这里称之为全局指令。 set 创建一个键值对
小手冰凉
2020/07/14
3650
Redis基础知识(一)
Redis 是一个开源的使用 ANSI C 语言编写、遵守 BSD 协议、支持网络、可基于内存亦可持久化的日志型、Key-Value 数据库,并提供多种语言的 API。 它通常被称为数据结构服务器,因为值(value)可以是 字符串(String), 哈希(Map),列表(list),集合(sets)和 有序集合(sorted sets)等类型。
没有故事的陈师傅
2019/12/11
1.4K0
Redis 常用操作命令,非常详细!
nx:如果key不存在则建立,xx:如果key存在则修改其值,也可以直接使用setnx/setex命令。
Java技术栈
2018/11/30
3K0
Redis(2):常用命令详解
redis命令不区分大小写 通用命令: 1. 获得符合规则的键名列表: keys pattern    其中pattern符合glob风格  ? (一个字符) * (任意个字符) [] (匹配其中的
SecondWorld
2018/03/14
1.1K0
Redis基础(超详解)一 :Redis定义、SQL与NoSQL区别、Redis常用命令、Redi五种数据类型String、List、Set、Hash、ZSet
Redis诞生于2009年,全称是Remote Dictionary Server,远程词典服务器,是一个开源、基于内存的键值型NoSQL数据库。
寻求出路的程序媛
2024/07/03
9610
Redis基础(超详解)一 :Redis定义、SQL与NoSQL区别、Redis常用命令、Redi五种数据类型String、List、Set、Hash、ZSet
相关推荐
Redis最基础内容
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验