Spring Data JPA - 如何创建查询(8)SpEL表达式

作者简介

陈喆,现就职于中科院某研究所担任副研究员,专注于工业云平台、MES系统的设计与研发。

内容来源:https://docs.spring.io/spring-data/jpa/docs/2.0.9.RELEASE/reference/html/#jpa.query.spel-expressions

从Spring Data JPA 1.4版本开始,支持在@Query定义的查询中使用SpEL模板表达式。在执行查询的时候,这些表达式通过一个事先定义好的变量集合求值。Spring Data JPA支持成为entityName的变量。它的用法是select x from #{#entityName} x。它会将域类型的entityName与给定repository关联起来。entityName按照如下方式处理:如果域类型在@Entity注解上设置了name属性,则使用该属性。否则直接使用域类型的类名。

下例演示了在定义带有查询方法和手工定义查询的repository接口时使用#{#entityName}表达式。

@Entity
public class User {

  @Id
  @GeneratedValue
  Long id;

  String lastname;
}

public interface UserRepository extends JpaRepository {

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

如果要避免在@Query注解中使用真实的实体名称,可以使用#{#entityName}变量。

当然,你可以在查询声明中直接使用User,但这会导致你需要修改查询。引用#{#entityName}还可以实现将User类映射到不同的实体名称上(例如,通过@Entity(name = "MyUser"

另一个#{#entityName}表达式的使用场景是如果你想定义一个通用的repository接口和一个用于具体域类型的指定repository接口。为了避免重复定义具体接口中的自定义查询方法,你可以在通用接口中使用实体名称表达式:

@MappedSuperclass
public abstract class AbstractMappedType {
  …
  String attribute
}

@Entity
public class ConcreteType extends AbstractMappedType { … }

@NoRepositoryBean
public interface MappedTypeRepository
  extends Repository {

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

public interface ConcreteRepository
  extends MappedTypeRepository { … }

在上例中,MappedTypeRepository接口是父接口,应用于扩展了AbstractMappedType的域类型。它定义了一个通用方法findAllByAttribute(…),可在子repository接口调用。如果你在ConcreteRepository调用findByAllAttribute(…),查询将转换为select t from ConcreteType t where t.attribute = ?1

 

你可能感兴趣的:(spring,spring,data)