【回炉重造】JPA(Java/Jakarta Persistence API)

JPA(Java/Jakarta Persistence API)

相关链接:

Give it a definition

JPA(Java/Jakarta Persistence API)是 Java 的持久化标准,用于将 Java 对象持久化到数据库中。

🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇
🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇🐇

简要说明

JPA(Java/Jakarta Persistence API)是 Java 的持久化标准,用于将 Java 对象持久化到数据库中。它提供了一种基于 POJO(Plain Old Java(Objects)的方式来管理数据库的数据,使得开发人员可以更方便地进行对象关系映射(ORM)操作。 目前主要有甲骨文和雅加达两个社区维护JPA标准,各有各的JPA标准,但大差不差,雅加达对高版本的JDK(>9)有更好的支持。

🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔
🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔🦔

版本

未被认可: 1.0
开天辟地: 2.0(Java6)
加点功能: 2.1(Java7)
加点成分: 2.2(Java8)
加卡塔: 3.0(Jakarta9)
加一点卡塔: 3.1(Jakarta10)

🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢
🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢🐢

Java Persistence的四个部分

API: The Java Persistence API

查询语言: The query language

持久化标准API: The Java Persistence Criteria API

对象关系映射元数据: Object/relational mapping metadata

🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳
🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳

Java Persistence的四个内容

实体: Entities

实体继承: Entity Inheritance

实体管理: Managing Entities

查询实体: Querying Entities

🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐
🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐🐐

实体Entities

实体是一种轻量级的持久化领域对象。通常情况下,一个实体代表着关系型数据库中的一张表,而每个实体实例对应着该表中的一行数据。实体的主要编程元素是实体类,尽管实体也可以使用辅助类。

实体的持久状态通过持久字段或持久属性来表示。这些字段或属性使用对象/关系映射注解将实体和实体关系映射到底层数据存储中的关系型数据中。

对实体类的要求
  • 类必须使用@Entity注解
  • 类必须有public, protected 或 无访问修饰符的无参构造函数,可以有其他构造函数
  • 类不可以是final类,任何方法和持久实例变量不能是final的
  • 如果实体实例作为一个分离对象(例如通过会话Bean的远程业务接口)以值传递的方式传递,那么该类必须实现 Serializable 接口。
  • 实体可以同时扩展实体类和非实体类,非实体类也可以扩展实体类
  • 持久化实例变量必须声明为 private、protected 或 package-private,并且只能通过实体类的方法直接访问。客户端必须通过访问器或业务方法访问实体的状态
实体类中的持久化字段和属性

基本数据类型,String,BigInteger,BigDecimal,Date,Calendar,Time,TimeStamp,Byte[],byte[],char[],Character[],用户定义的可序列化类型,枚举类型,
其他实体或实体集合,可嵌入类

持久字段

transient字段不存

持久属性

要有getter和setter

在实体字段和属性中使用集合
  • 只能用Collection,Set,List,Map
  • 实体元素和关系的集合可以由java.util.Map集合表示。映射 由键和值组成。
  • 当Map值是可嵌入类或基本类型时用ElementClollection注解
  • 当Map值是实体时,使用@OneToMany或@ManyToMany注解。
  • 仅在双向关系的一侧使用映射类型
  • @MapKeyClasss, @MapKey, @ElementCollection, @JoinColumn, @OneToMany, @ManyToMany
验证持久化字段和属性
  • 使用@NotNull,@Pattern,@Temporal等注解
实体中的主键
  • 每个实体都必须有一个主键
  • 简单主键用@Id,符合主键用@EmbeddedId和@IdClass
  • 主键的类型只能是: 原始类型,原始类型的包装类型,String,util.Date,sql.Date,BigDecimal,BigInteger。绝对不可以用带浮点数的类型
  • 主键类必须满足的要求:略
实体关系的多重性
  • @OneToOne,@OneToMany,@ManyToOne,@ManyToMany
实体关系中的方向
  • 实体关系中的方向决定了持久化时如何更新数据库
双向关系
  • 双向关系必须遵循这些规则。

双向关系的反面必须通过使用@OneToOne、@OneToMany或@ManyToMany注释的mappedBy元素来引用其拥有方。mappedBy元素指定作为关系所有者的实体中的属性或字段。
多对一双向关系的多方不得定义mappedBy元素。关系中的多方始终是拥有方。
对于一对一的双向关系,拥有方对应于包含相应外键的一方。
对于多对多的双向关系,任何一方都可以是拥有方

单向关系

在单向关系中,只有一个实体具有引用另一个实体的关系字段或属性

查询和关系方向

Java 持久性查询语言和 Criteria API 查询通常跨关系进行导航

级联操作和关系

使用关系的实体通常依赖于关系中其他实体的存在。

级联操作

  • 全部

所有级联操作都将应用于父实体的相关实体。全部相当于指定cascade={DETACH, MERGE, PERSIST, REFRESH, REMOVE}

  • 分离

如果父实体从持久化上下文中分离,相关实体也将被分离。

  • 合并

如果父实体被合并到持久化上下文中,相关实体也将被合并。

  • 坚持

如果父实体被持久化到持久化上下文中,相关实体也将被持久化。

  • 刷新

如果父实体在当前持久化上下文中刷新,相关实体也会被刷新。

  • 消除

如果父实体从当前持久化上下文中删除,相关实体也将被删除。

关系中的孤儿移除

当一对一或一对多关系中的目标实体从关系中删除时,通常需要将删除操作级联到目标实体

实体中的嵌入类
  • 可嵌入类用于表示实体的状态,但与实体类不同,它们没有自己的持久标识。可嵌入类的实例共享拥有它的实体的标识。可嵌入类仅作为另一个实体的状态而存在。实体可以具有单值或集合值的可嵌入类属性。

  • 可嵌入类与实体类具有相同的规则,但使用javax.persistence.Embeddable注释而不是@Entity进行注释。
    拥有可嵌入类作为其持久状态一部分的实体可以使用javax.persistence.Embedded注释来注释字段或属性,但不要求这样做。

  • 可嵌入类本身可以使用其他可嵌入类来表示它们的状态。它们还可能包含基本 Java 编程语言类型或其他可嵌入类的集合。

  • 可嵌入类还可以包含与其他实体或实体集合的关系。如果可嵌入类具有这样的关系,则该关系是从目标实体或实体集合到拥有可嵌入类的实体。

🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕
🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕🐕

管理实体Managing Entities

🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽
🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽🐽

查询实体Querying Entities

🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱
🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱🥱

更多持久化内容Further Information about Persistence

🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐
🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐🧐

其他内容

Running the Persistence Examples

The Java Persistence Query Language

Using the Criteria API to Create Queries

Creating and Using String-Based Criteria Queries

Controlling Concurrent Access to Entity Data with Locking

Using a Second-Level Cache with Java Persistence API Applications

🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸
🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸🐸

JPA的重要概念和特点

1. 对象关系映射(ORM)

  • JPA 是一种 ORM 框架,允许开发人员使用普通的 Java 对象(POJOs)来代表数据库中的表,以及使用注解或 XML 映射文件来定义对象和表之间的映射关系。

2. 实体(Entity)

  • 实体是一个普通的 Java 类,使用 @Entity 注解来标识。每个实体类对应数据库中的一张表,实体类的属性对应表中的列。

3. 主键(Primary Key)

  • 实体类的主键用 @Id 注解标识,表示它是表中的主键。

4. 实体管理器(EntityManager)

  • EntityManager 是 JPA 的核心接口之一,用于管理实体的生命周期,执行 CRUD 操作,以及执行查询操作。

5. 持久化上下文(Persistence Context)

  • 持久化上下文是 EntityManager 管理实体的上下文环境,它跟踪实体的状态(新建、托管、脱管、删除等),并负责将实体同步到数据库。

6. JPQL(Java Persistence Query Language)

  • JPQL 是 JPA 提供的查询语言,类似于 SQL,但是使用实体类和属性的名称来进行查询。它支持多种查询操作,包括条件查询、聚合查询、连接查询等。

7. 命名查询(Named Queries)

  • 命名查询是预定义的 JPQL 查询,可以在实体类上使用 @NamedQuery 注解定义。这些查询可以在应用程序的任何地方被调用。

8. 关联关系(Relationships)

  • JPA 支持多种关联关系,如一对一、一对多、多对一、多对多等。可以使用 @OneToOne@OneToMany@ManyToOne@ManyToMany 等注解来定义关联关系。

9. 事务管理

  • JPA 支持事务管理,可以使用编程式或声明式的方式管理事务。开发人员可以使用 @Transactional 注解或编程式事务 API 来定义和管理事务。

10. 缓存支持

  • JPA 提供了一级缓存(EntityManager 级别的缓存)和二级缓存(应用程序级别的缓存)的支持,可以提高应用程序的性能。

11. 生命周期回调(Lifecycle Callbacks)

  • JPA 允许开发人员在实体对象的生命周期中定义回调方法,如在实体创建、加载、更新、删除等事件发生时触发特定的方法。

使用 JPA 的基本流程:

  1. 定义实体类,使用 @Entity@Id 等注解标识实体类和主键。

  2. 配置数据源和 JPA 属性,通常在 persistence.xml 配置文件中配置。

  3. 创建 EntityManagerFactory 对象,通常使用 Persistence.createEntityManagerFactory("persistence-unit-name") 方法。

  4. 通过 EntityManagerFactory 创建 EntityManager 对象,用于管理实体的生命周期。

  5. 开始事务,执行 CRUD 操作,包括持久化、加载、更新、删除等。

  6. 提交或回滚事务。

  7. 关闭 EntityManager。

以下是一个简单的 JPA 示例,演示了如何定义一个 User 实体类并进行持久化:

@Entity
@Table(name = "users")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String username;

    private String email;

    // Getters and setters
}

// 使用 JPA 进行数据操作
EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("persistence-unit-name");
EntityManager entityManager = entityManagerFactory.createEntityManager();
EntityTransaction transaction = entityManager.getTransaction();

try {
    // 开始事务
    transaction.begin();

    // 创建一个新用户
    User user = new User();
    user.setUsername("john_doe");
    user.setEmail("john@example.com");

    // 持久化用户到数据库
    entityManager.persist(user);

    // 提交事务
    transaction.commit();
} catch (Exception e) {
    // 发生异常时回滚事务
    if (transaction.isActive()) {
        transaction.rollback();
    }
    e.printStackTrace();
} finally {
    // 关闭 EntityManager
    entityManager.close();
    entityManagerFactory.close();
}

这只是一个简单的示例,JPA 还提供了更多功能和选项,如查询、关联关系、命名查询等。使用 JPA 可以大大简化和提高 Java 应用程序与数据库的交互。

😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎
😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎

多对多@ManyToMany

在进行多对多关系的查询时,如果您希望查询一个实体(例如 Course),但是 JPA 自动生成的 SQL 中包含了 EXISTS 子查询,判断在中间表(例如 student_course)中是否有对应的数据,这通常是因为 JPA 的默认加载策略是延迟加载(FetchType.LAZY)引起的。

当您在 StudentCourse 实体类中使用 @ManyToMany 注解时,默认情况下,这种关系是延迟加载的。这意味着,当您从数据库中查询一个 Course 对象时,并不会立即查询与之相关联的 Student 对象,直到您真正访问 Course 对象的 students 属性时才会触发额外的 SQL 查询。

原因解释:

  1. 默认延迟加载:JPA 默认使用延迟加载策略,以减少数据库查询的数量。这意味着,当您从数据库中检索一个 Course 对象时,JPA 不会立即加载与之关联的 Student 对象。它会等到您访问 Course 对象的 students 属性时才会去数据库中查询。

  2. 触发额外查询:当您访问 Course 对象的 students 属性时,JPA 需要判断在中间表 student_course 中是否存在与当前 Course 对象相关联的记录。因此,它会生成一个 EXISTS 子查询,检查中间表中是否存在符合条件的记录。

解决方法:

如果您希望在查询 Course 对象时立即获取与之关联的 Student 对象,可以考虑以下几种方法:

1. 使用 FetchType.EAGER
  • 您可以在 Course 实体类中的 students 属性上添加 FetchType.EAGER 注解,将加载策略设置为立即加载。
  • 这样,当您从数据库中查询 Course 对象时,与之关联的 Student 对象也会立即加载。
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(
    name = "student_course",
    joinColumns = @JoinColumn(name = "course_id"),
    inverseJoinColumns = @JoinColumn(name = "student_id")
)
private Set<Student> students = new HashSet<>();
2. 使用 JOIN FETCH 查询:
  • 在进行查询时,可以使用 JPQL(Java Persistence Query Language)或者 Criteria API 来手动指定使用 JOIN FETCH 进行关联对象的立即加载。
  • 这样在查询时就会一并加载关联对象,避免额外的 EXISTS 子查询。
String jpql = "SELECT c FROM Course c JOIN FETCH c.students WHERE c.id = :courseId";
Course course = entityManager.createQuery(jpql, Course.class)
                            .setParameter("courseId", courseId)
                            .getSingleResult();
3. 使用 @EntityGraph 注解:
  • 您也可以使用 @EntityGraph 注解来定义在查询时加载关联对象的方式。
  • 这种方式可以在实体类上定义一个名为 students@NamedEntityGraph,并在查询时指定加载策略。
@NamedEntityGraph(name = "Course.students", attributeNodes = @NamedAttributeNode("students"))
@Entity
public class Course {
    // ...
}

然后在查询时使用该 @EntityGraph

EntityGraph<Course> graph = entityManager.createEntityGraph(Course.class);
graph.addAttributeNodes("students");

Course course = entityManager.find(Course.class, courseId, Collections.singletonMap("javax.persistence.loadgraph", graph));

通过以上方法,您可以根据具体需求选择合适的加载策略,从而解决在查询 Course 对象时生成额外的 EXISTS 子查询的问题。

😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏
😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏😏

方法名查询

在使用 Spring Data JPA 时,如果您定义的自定义方法名称符合一定的命名规则,Spring Data JPA 将会根据方法名自动生成对应的 SQL 查询。这个特性称为方法名查询(Method Name Query)。

方法名查询的规则:

Spring Data JPA 提供了一系列命名规则,它们可以让您在命名方法时,根据方法名自动生成 SQL 查询。

下面是一些常见的命名规则和示例:

  1. 基本的查询

    • 根据属性名进行查询,例如 findByreadByqueryBycountBy 等后面跟着属性名称。
    • 示例:根据学生的名字查询
      Student findByName(String name);
      
  2. 使用多个属性进行查询

    • 使用 AndOrBetween 等关键字进行组合查询。
    • 示例:根据学生的名字和年龄查询
      Student findByNameAndAge(String name, int age);
      
  3. 模糊查询

    • 使用 Like 关键字进行模糊查询。
    • 示例:根据学生的名字模糊查询
      List<Student> findByNameLike(String name);
      
  4. 排序查询

    • 使用 OrderBy 关键字进行排序查询。
    • 示例:根据学生的年龄升序查询
      List<Student> findByOrderByAgeAsc();
      
  5. 分页查询

    • 使用 TopFirstLast 等关键字进行分页查询。
    • 示例:查询前两个年龄最大的学生
      List<Student> findTop2ByOrderByAgeDesc();
      
  6. 统计查询

    • 使用 CountDistinct 等关键字进行统计查询。
    • 示例:统计学生的数量
      long countByName(String name);
      
  7. 自定义查询

    • 如果方法名查询的规则不能满足您的需求,您也可以使用 @Query 注解和 JPQL 或者 SQL 进行自定义查询。
    • 示例:使用 JPQL 进行自定义查询
      @Query("SELECT s FROM Student s WHERE s.age > :age")
      List<Student> findByAgeGreaterThan(@Param("age") int age);
      

原理解释:

Spring Data JPA 通过解析方法名,根据方法名中的规则来生成对应的 JPQL 或者 SQL 查询。例如,在命名为 findByName 的方法中,它会识别出 Name 作为属性名,并生成类似于 SELECT * FROM Student WHERE name = ? 的 SQL 查询。

这种方法名查询的机制大大简化了开发者编写常规查询的工作,同时也提高了代码的可读性和可维护性。

如果您需要更复杂的查询,可以使用 @Query 注解和 JPQL 或者 SQL 来编写自定义查询。这样可以满足更灵活的查询需求。

总的来说,Spring Data JPA 的方法名查询是根据方法名的命名规则自动生成 SQL 查询,让开发者更专注于业务逻辑,同时提高了开发效率。

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值