5.3.7. 使用SpEL表达式

5.3.7. 使用SpEL表达式

5.3.7. Using SpEL Expressions

从Spring Data JPA发布1.4版本时,支持使用@Query手动定义查询来支持严格的SpEL模板表达式。在查询执行时,这些表达式通过一系列预设的变量进行评估。Spring Data JPA支持entityName变量。用法为select x from #{#entityName} x。会把entityName插入关联指定库的领域类型。entityName会按如下解析:如果领域类型有@Entity注解的名称属性,则会使用此名称。否则将使用领域类型的简单类名。

As of Spring Data JPA release 1.4, we support the usage of restricted SpEL template expressions in manually defined queries that are defined with @Query. Upon query execution, these expressions are evaluated against a predefined set of variables. Spring Data JPA supports a variable called entityName. Its usage is select x from #{#entityName} x. It inserts the entityName of the domain type associated with the given repository. The entityName is resolved as follows: If the domain type has set the name property on the @Entity annotation, it is used. Otherwise, the simple class-name of the domain type is used.

下面的例子展示了在你想定义一个有查询方法和手动定义查询的库的查询字符串中的#{#entityName}表达式的一种用法。

The following example demonstrates one use case for the #{#entityName} expression in a query string where you want to define a repository interface with a query method and a manually defined query:

例62. 在库查询方法中使用SpEL表达式 – entityName

Example 62. Using SpEL expressions in repository query methods – entityName

@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);
}

为了避免声明@Query注解查询字符串中的实际实体名,你可以使用#{#entityName}变量。

To avoid stating the actual entity name in the query string of a @Query annotation, you can use the #{#entityName} variable.

当然,你可以在查询声明中直接使用User,但同时也需要改变查询。#entityName参考将选择潜在的期望并将User类匹配到一个不同的实体名称(例如,使用@Entity(name = "MyUser"))。

Of course, you could have just used User in the query declaration directly, but that would require you to change the query as well. The reference to #entityName picks up potential future remappings of the User class to a different entity name (for example, by using @Entity(name = "MyUser")).

另一个在查询字符串中使用#{#entityName}表达式的例子是,如果你想用特定库为实体领域类型来定义一个泛型库接口。不要在实体接口中重复定义自定义查询方法,你可以在泛型库接口的@Query注解的查询字符串中使用实体名称表达式,如下例所示:

Another use case for the #{#entityName} expression in a query string is if you want to define a generic repository interface with specialized repository interfaces for a concrete domain type. To not repeat the definition of custom query methods on the concrete interfaces, you can use the entity name expression in the query string of the @Query annotation in the generic repository interface, as shown in the following example:

例63. 在库查询方法中使用SpEL表达式 – 继承的entityName

Example 63. Using SpEL expressions in repository query methods – entityName with inheritance

@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> { … }

在上述例子中,MappedTypeRepository接口是一个用于一些领域类型的公共父接口,继承了AbstractMappedType。还定义了泛型findAllByAttribute(…)方法,用于返回指定库接口的实例。如果你调用ConcreteRepositoryfindByAllAttribute(…)方法,查询会变为select t from ConcreteType t where t.attribute = ?1

In the preceding example, the MappedTypeRepository interface is the common parent interface for a few domain types extending AbstractMappedType. It also defines the generic findAllByAttribute(…) method, which can be used on instances of the specialized repository interfaces. If you now invoke findByAllAttribute(…) on ConcreteRepository, the query becomes select t from ConcreteType t where t.attribute = ?1.

翻译部分版权归YahaCode团队所有。仅供学习研究之用,任何组织或个人不得私自以此用于任何形式的商业目的

发表评论