SpringDataJPA了解篇

JPA是JavaEE标准,提供面向对象的ORM解决方案,简化数据库操作。SpringDataJPA是Spring框架的一部分,基于JPA提供更便捷的数据库交互,包括自动化CRUD、查询方法自动生成等。EntityManager是JPA的核心接口,管理实体生命周期和数据库交互。CrudRepository和JpaRepository等接口则为开发者提供了方便的数据库操作API。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、JPA是什么

JPA 是 JCP 组织发布的 Java EE 标准之一,因此任何声称符合 JPA 标准的框架都遵循同样的架构,提供相同的访问API,这保证了基于JPA开发的企业应用能够经过少量的修改就能够在不同的JPA框架下运行。

JPA 提供了一种标准化的、面向对象的方式来处理对象与关系数据库之间的映射和持久化操作。它提供了丰富的注解和接口,使开发人员能够更轻松地进行数据库操作,同时提高了代码的可移植性和可维护性,用于简化对象关系映射(ORM)的开发工作。JPA 是 Java EE(现在称为 Jakarta EE)的一部分,并且可以与任何支持 JPA 规范的 ORM 框架一起使用,最著名的实现是 Hibernate。

核心概念:

  1. 实体(Entity):实体是应用程序中持久化到数据库的对象。在 JPA 中,实体通常映射到数据库中的表,并且实体类使用 @Entity 注解进行标识。
  2. 属性(Attributes):实体类的属性对应于数据库表的列。JPA 使用注解(如 @Column)来指定属性与列的映射关系,包括列名、数据类型、长度、索引等。
  3. 主键(Primary Key):每个实体都必须有一个主键,用于唯一标识实体。JPA 提供了多种方式来定义主键,包括自动生成、手动指定、复合主键等。
  4. 关联关系(Relationship):JPA 支持在实体之间建立关联关系,如一对一、一对多、多对一和多对多。关联关系使用注解(如 @OneToOne@OneToMany@ManyToOne@ManyToMany)进行标识。
  5. EntityManager:EntityManager 是 JPA 的核心接口之一,用于管理实体对象的生命周期和执行数据库操作。它提供了持久化(保存、更新、删除)、查询、事务管理等功能。
  6. JPQL(Java Persistence Query Language):JPQL 是一种面向对象的查询语言,类似于 SQL,但是操作的是实体对象而不是表和列。JPQL 允许开发人员以对象模型的方式编写查询语句,从而提供了更加灵活和面向对象的查询能力。
  7. ORM(Object-Relational Mapping):ORM 是一种将关系型数据库和面向对象编程语言之间数据的转换技术。JPA 提供了一种方便的 ORM 实现,通过注解和配置,可以实现实体对象与数据库表之间的映射,从而实现对象与数据库之间的转换和持久化。

2、SpringDataJPA是什么

Spring Data JPA 是 Spring 框架提供的一个用于简化与数据库交互的模块。它基于 Java Persistence API(JPA)规范,并提供了许多便捷的功能,使得在使用关系型数据库时更加容易和高效。

SpringDataJPA的功能:

  1. 对象关系映射(ORM):Spring Data JPA 提供了一种简单的方式来将 Java 对象与数据库表之间进行映射。通过使用注解或 XML 配置,可以定义实体类、表之间的关系以及字段的映射规则,从而将对象持久化到数据库中。
  2. 自动化 CRUD 操作:Spring Data JPA 提供了自动化的 CRUD(创建、读取、更新、删除)操作。只需定义接口,并继承 CrudRepositoryJpaRepository 接口,就可以获得常见的数据库操作方法,如保存实体、查询实体、删除实体等,无需手动编写常见的 CRUD 代码。
  3. 查询方法的自动生成:Spring Data JPA 根据方法命名规则自动生成查询语句。例如,根据方法名 findByFirstName(String firstName) 自动生成的查询语句将查找指定 firstName 的实体。还可以使用更复杂的命名规则来生成更复杂的查询语句。
  4. 分页和排序:Spring Data JPA 支持轻松实现分页和排序功能。通过在方法中传递 Pageable 对象,可以在查询中指定页数、每页条数以及排序规则,从而方便地进行分页查询。
  5. 复杂查询支持:Spring Data JPA 支持使用 JPA Criteria 查询、JPQL(Java Persistence Query Language)查询和本地 SQL 查询等多种查询方式,以满足复杂查询需求。
  6. 事务管理:Spring Data JPA 集成了 Spring 的事务管理功能,可以通过简单的配置实现对数据库事务的管理,确保数据的一致性和完整性。
  7. 异步查询:Spring Data JPA 还提供了异步查询的支持,通过使用 @Async 注解,可以在执行查询时异步地处理数据库操作,提高系统的并发性能。

3、核心概念

3.1、CrudRepository

public interface CrudRepository<T, ID> extends Repository<T, ID> {

  <S extends T> S save(S entity);// 1   

  Optional<T> findById(ID primaryKey);// 2 

  Iterable<T> findAll();// 3               

  long count();// 4                        

  void delete(T entity);// 5             

  boolean existsById(ID primaryKey);// 6

  // … more functionality omitted.
}

  1. 保存一个给定的对象
  2. 通过id(主键)查询对象
  3. 查询所有对象
  4. 查询所有对象的总数
  5. 删除给定的对象
  6. 判断给定的id(主键)是否存在

3.2、JpaRepository

3.3、PagingAndSortingRepository

public interface PagingAndSortingRepository<T, ID> extends CrudRepository<T, ID> {

  Iterable<T> findAll(Sort sort);

  Page<T> findAll(Pageable pageable);
}

PagingAndSortingRepository<User, Long> repository = // … get access to a bean
Page<User> users = repository.findAll(PageRequest.of(1, 20));

3.4、分页和排序

Sort sort = Sort.by("firstname").ascending()
  .and(Sort.by("lastname").descending());

TypedSort<Person> person = Sort.sort(Person.class);

Sort sort = person.by(Person::getFirstname).ascending()
  .and(person.by(Person::getLastname).descending());

QSort sort = QSort.by(QPerson.firstname.asc())
  .and(QSort.by(QPerson.lastname.desc()));

3.5、支持的方法名查询

关键词样本JPQL 片段
DistinctfindDistinctByLastnameAndFirstnameselect distinct … where x.lastname = ?1 and x.firstname = ?2
AndfindByLastnameAndFirstname… where x.lastname = ?1 and x.firstname = ?2
OrfindByLastnameOrFirstname… where x.lastname = ?1 or x.firstname = ?2
Is, EqualsfindByFirstname,findByFirstnameIs,findByFirstnameEquals… where x.firstname = ?1
BetweenfindByStartDateBetween… where x.startDate between ?1 and ?2
LessThanfindByAgeLessThan… where x.age < ?1
LessThanEqualfindByAgeLessThanEqual… where x.age <= ?1
GreaterThanfindByAgeGreaterThan… where x.age > ?1
GreaterThanEqualfindByAgeGreaterThanEqual… where x.age >= ?1
AfterfindByStartDateAfter… where x.startDate > ?1
BeforefindByStartDateBefore… where x.startDate < ?1
IsNull,NullfindByAge(Is)Null… where x.age is null
IsNotNull,NotNullfindByAge(Is)NotNull… where x.age not null
LikefindByFirstnameLike… where x.firstname like ?1
NotLikefindByFirstnameNotLike… where x.firstname not like ?1
StartingWithfindByFirstnameStartingWith… where x.firstname like ?1(附加绑定的参数%
EndingWithfindByFirstnameEndingWith… where x.firstname like ?1(带前缀的参数绑定%
ContainingfindByFirstnameContaining… where x.firstname like ?1(包裹在 中的参数绑定%
OrderByfindByAgeOrderByLastnameDesc… where x.age = ?1 order by x.lastname desc
NotfindByLastnameNot… where x.lastname <> ?1
InfindByAgeIn(Collection<Age> ages)… where x.age in ?1
NotInfindByAgeNotIn(Collection<Age> ages)… where x.age not in ?1
TruefindByActiveTrue()… where x.active = true
FalsefindByActiveFalse()… where x.active = false
IgnoreCasefindByFirstnameIgnoreCase… where UPPER(x.firstname) = UPPER(?1)

3.6、@Query使用

public interface UserRepository extends JpaRepository<User, Long> {

  @Query("select u from User u where u.emailAddress = ?1")
  User findByEmailAddress(String emailAddress);
}

like查询:

public interface UserRepository extends JpaRepository<User, Long> {

  @Query("select u from User u where u.firstname like %?1")
  List<User> findByFirstnameEndsWith(String firstname);
}

nativeQuery查询:

  1. nativeQuery = false 未开启(默认情况):
    • 使用 JPA 提供的查询语言(JPQL)执行查询操作。
    • 查询语句使用实体类和属性的名称,而不是数据库的表名和列名。
    • JPA 会根据实体类的映射关系,自动生成适当的 SQL 查询语句。
    • JPA 可以提供更高级的特性,如延迟加载、级联操作等。
  2. nativeQuery = true 开启:
    • 使用原生 SQL 查询语句执行查询操作。
    • 查询语句直接使用数据库的表名和列名。
    • 开发人员需要手动编写 SQL 查询语句,并负责处理实体类与查询结果之间的映射关系。
    • 可以使用 SQL 的特性和语法,如复杂的联接查询、存储过程调用等。
    • JPA 提供的高级特性(如延迟加载、级联操作)可能不适用于原生查询结果,需要开发人员自行处理。
public interface UserRepository extends JpaRepository<User, Long> {

  @Query(value = "SELECT * FROM USERS WHERE EMAIL_ADDRESS = ?1", nativeQuery = true)
  User findByEmailAddress(String emailAddress);
}

分页查询,并且获取总数:

public interface UserRepository extends JpaRepository<User, Long> {

  @Query(value = "SELECT * FROM USERS WHERE LASTNAME = ?1",
    countQuery = "SELECT count(*) FROM USERS WHERE LASTNAME = ?1",
    nativeQuery = true)
  Page<User> findByLastname(String lastname, Pageable pageable);
}

排序:

public interface UserRepository extends JpaRepository<User, Long> {

  @Query("select u from User u where u.lastname like ?1%")
  List<User> findByAndSort(String lastname, Sort sort);

  @Query("select u.id, LENGTH(u.firstname) as fn_len from User u where u.lastname like ?1%")
  List<Object[]> findByAsArrayAndSort(String lastname, Sort sort);
}

repo.findByAndSort("lannister", Sort.by("firstname"));// 1               
repo.findByAndSort("stark", Sort.by("LENGTH(firstname)"));// 2            
repo.findByAndSort("targaryen", JpaSort.unsafe("LENGTH(firstname)"));// 3 
repo.findByAsArrayAndSort("bolton", Sort.by("fn_len"));// 4  

  1. 有效
  2. 无效
  3. 有效
  4. 有效,指向别名

别名传参:

public interface UserRepository extends JpaRepository<User, Long> {

  @Query("select u from User u where u.firstname = :firstname or u.lastname = :lastname")
  User findByLastnameOrFirstname(@Param("lastname") String lastname,
                                 @Param("firstname") String firstname);
}

SpEL 表达式:

@Entity
public class User {

  @Id
  @GeneratedValue
  Long id;

  String lastname;
}

public interface UserRepository extends JpaRepository<User,Long> {

  @Query("select u from #{#entityName} u where u.lastname = ?1")
  List<User> findByLastname(String lastname);
}

@MappedSuperclass
public abstract class AbstractMappedType {String attribute
}

@Entity
public class ConcreteType extends AbstractMappedType {}

@NoRepositoryBean
public interface MappedTypeRepository<T extends AbstractMappedType>
  extends Repository<T, Long> {

  @Query("select t from #{#entityName} t where t.attribute = ?1")
  List<T> findAllByAttribute(String attribute);
}

public interface ConcreteRepository
  extends MappedTypeRepository<ConcreteType> {}

@Query("select u from User u where u.firstname = ?1 and u.firstname=?#{[0]} and u.emailAddress = ?#{principal.emailAddress}")
List<User> findByFirstnameAndCurrentUserWithCustomQuery(String firstname);

?#{[0]}表示获取这个方法的第一个参数

?#{principal.emailAddress}表示获取SpringSecurity中登录用户的邮箱

@Query("select u from User u where u.lastname like %:#{[0]}% and u.lastname like %:lastname%")
List<User> findByLastnameWithSpelExpression(@Param("lastname") String lastname);

// sql注入问题

转义%、_模糊查询通配符:

@Query("select u from User u where u.firstname like %?#{escape([0])}% escape ?#{escapeCharacter()}")
List<User> findContainingEscaped(String namePart);

声明更新语句:

@Modifying
@Query("update User u set u.firstname = ?1 where u.lastname = ?2")
int setFixedFirstnameFor(String firstname, String lastname);

声明删除语句:

interface UserRepository extends Repository<User, Long> {

  void deleteByRoleId(long roleId);

  @Modifying
  @Query("delete from User u where u.role.id = ?1")
  void deleteInBulkByRoleId(long roleId);
}

4、EntityManager

在 Spring Data JPA 中,EntityManager 是用于与持久化上下文交互的关键接口之一。它提供了对持久化操作的管理和执行能力。下面是 EntityManager 的几个主要作用:

  1. 实体管理:EntityManager 负责管理实体对象的生命周期,包括实体对象的创建、加载、持久化、合并和删除等操作。它允许你对实体进行增删改查操作,以及对实体对象的属性进行修改和跟踪。
  2. 持久化操作:EntityManager 提供了持久化操作的方法,如 persist()、merge()、remove() 等。你可以使用 EntityManager 将实体对象持久化到数据库中,从数据库中加载实体对象,更新实体对象的状态,以及删除实体对象。
  3. 事务管理:EntityManager 支持事务管理,你可以通过 EntityManager 开启、提交或回滚事务,以保证数据的一致性和完整性。它与 Spring 的事务管理机制集成,可以与 Spring 的事务注解或编程式事务管理一起使用。
  4. 查询操作:EntityManager 提供了创建和执行查询的能力。你可以使用 EntityManager 创建 JPQL(Java Persistence Query Language)查询、本地 SQL 查询或命名查询,并对查询结果进行处理和操作。
  5. 缓存管理:EntityManager 管理实体对象的缓存,提供了一级缓存(即持久化上下文)的功能。通过 EntityManager,你可以控制实体对象的缓存策略、清除缓存、刷新缓存等操作,以提高查询性能和减少数据库访问。

EntityManager用于管理实体对象的生命周期、执行持久化操作、处理事务、执行查询和管理缓存等。它是与底层数据库交互的核心接口,为应用程序提供了便捷的持久化操作和管理功能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值