@Query注解的用法(Spring Data JPA)

本文介绍了使用Spring Data JPA实现复杂查询的方法,包括@Query注解的基本使用、Like表达式、Native SQL查询、参数注入及SPEL表达式的应用等。

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

1. 一个使用@Query注解的简单例子

@Query(value = "select name,author,price from Book b where b.price>?1 and b.price<?2")
List<Book> findByPriceRange(long price1, long price2);

 

2.  Like表达式

@Query(value = "select name,author,price from Book b where b.name like %:name%")
List<Book> findByNameMatch(@Param("name") String name);

 

3. 使用Native SQL Query

所谓本地查询,就是使用原生的sql语句(根据数据库的不同,在sql的语法或结构方面可能有所区别)进行查询数据库的操作。

@Query(value = "select * from book b where b.name=?1", nativeQuery = true)
List<Book> findByName(String name);

 

4. 使用@Param注解注入参数

@Query(value = "select name,author,price from Book b where b.name = :name AND b.author=:author AND b.price=:price")
List<Book> findByNamedParam(@Param("name") String name, @Param("author") String author,
        @Param("price") long price);

 

5. SPEL表达式(使用时请参考最后的补充说明)

   '#{#entityName}'值为'Book'对象对应的数据表名称(book)。

public interface BookQueryRepositoryExample extends Repository<Book, Long>{

       @Query(value = "select * from #{#entityName} b where b.name=?1", nativeQuery = true)
       List<Book> findByName(String name);

}

 

6. 一个较完整的例子

复制代码

public interface BookQueryRepositoryExample extends Repository<Book, Long> {
    @Query(value = "select * from Book b where b.name=?1", nativeQuery = true) 
    List<Book> findByName(String name);// 此方法sql将会报错(java.lang.IllegalArgumentException),看出原因了吗,若没看出来,请看下一个例子

    @Query(value = "select name,author,price from Book b where b.price>?1 and b.price<?2")
    List<Book> findByPriceRange(long price1, long price2);

    @Query(value = "select name,author,price from Book b where b.name like %:name%")
    List<Book> findByNameMatch(@Param("name") String name);

    @Query(value = "select name,author,price from Book b where b.name = :name AND b.author=:author AND b.price=:price")
    List<Book> findByNamedParam(@Param("name") String name, @Param("author") String author,
            @Param("price") long price);

}

复制代码

 

7.  解释例6中错误的原因:

     因为指定了nativeQuery = true,即使用原生的sql语句查询。使用java对象'Book'作为表名来查自然是不对的。只需将Book替换为表名book。

@Query(value = "select * from book b where b.name=?1", nativeQuery = true)
List<Book> findByName(String name);

 

 

补充说明(2017-01-12):

  有同学提出来了,例子5中用'#{#entityName}'为啥取不到值啊?

  先来说一说'#{#entityName}'到底是个啥。从字面来看,'#{#entityName}'不就是实体类的名称么,对,他就是。

  实体类Book,使用@Entity注解后,spring会将实体类Book纳入管理。默认'#{#entityName}'的值就是'Book'。

  但是如果使用了@Entity(name = "book")来注解实体类Book,此时'#{#entityName}'的值就变成了'book'。

  到此,事情就明了了,只需要在用@Entity来注解实体类时指定name为此实体类对应的表名。在原生sql语句中,就可以把'#{#entityName}'来作为数据表名使用。

<think>嗯,用户问的是Spring Data JPA中的@Query注解是否支持ResultSetMapping属性。我需要先回忆一下相关的知识。记得在JPA中,@SqlResultSetMapping是用来处理原生SQL查询的结果映射的,尤其是在返回非实体类型或者部分字段的时候。而Spring Data JPA@Query注解通常用于定义自定义查询,可以是JPQL也可以是原生SQL。 然后,用户提供的引用里,引用[3]提到可以通过命名本机查询来处理返回非实体对象的情况,引用[4]则提到了使用@SqlResultSetMappings来接收查询结果。这说明当使用原生查询时,可能需要ResultSetMapping来映射结果,但@Query注解本身是否有这个属性呢? 接下来,我需要检查@Query注解的官方文档或者源码。根据记忆,@Query注解的主要属性有value、nativeQuery、countQuery等,但没有直接叫做resultSetMapping的属性。不过,可能可以通过其他方式关联,比如在实体类上定义@SqlResultSetMapping,然后在@Query中引用它的名字? 比如,用户可能在实体类中定义了@SqlResultSetMapping(name = "CustomMapping"),然后在Repository的@Query注解中使用这个映射。这时候,是否需要在@Query中指定resultSetMapping属性呢?或者是否需要使用其他注解或方法? 根据引用[4],使用@SqlResultSetMappings需要配合原生查询,并且可能在查询中通过ResultSetMapping的名称来引用。但是在Spring Data JPA@Query注解中,原生查询是通过设置nativeQuery=true来启用的,但如何指定ResultSetMapping呢? 查资料发现,@Query注解本身并不直接支持resultSetMapping属性。不过,可以通过在JPQL或原生SQL中使用JPA的语法来指定结果类,或者使用@NamedNativeQuery结合@SqlResultSetMapping,然后在Repository中引用这个命名查询。 比如,在实体类上定义@NamedNativeQuery和@SqlResultSetMapping,然后在Repository的方法上使用@Query(name = "NamedQueryName")来引用,这样就能间接使用ResultSetMapping了。但这是否属于@Query注解直接支持的功能呢?可能用户的问题在于是否可以在@Query中直接设置,而不是通过命名查询间接使用。 总结来说,@Query注解没有直接的resultSetMapping属性,但可以通过在实体类中配置@NamedNativeQuery和@SqlResultSetMapping,然后在Repository中通过@Query的name属性引用该命名查询,从而间接使用ResultSetMapping。此外,对于返回非实体类型,可以使用接口投影或DTO投影,这可能更简便。 用户可能实际的需求是如何处理原生查询返回的非实体结果,而ResultSetMapping是其中一种方法。因此,在回答时需要说明@Query不直接支持该属性,但可以通过其他方式实现类似功能,并给出示例和替代方案,如投影或构造函数表达式。</think>### Spring Data JPA@Query注解对ResultSetMapping的支持 #### 核心结论 **@Query注解本身不直接支持`ResultSetMapping`属性**,但可以通过以下方式间接实现类似功能: 1. 结合`@NamedNativeQuery`和`@SqlResultSetMappings`定义映射规则 2. 使用DTO投影或接口投影简化结果映射[^3][^4] --- ### 分步说明 #### 1. 原生查询与`@SqlResultSetMappings` 若需通过原生SQL返回非实体对象,需在实体类中定义映射规则: ```java // 实体类定义 @SqlResultSetMappings({ @SqlResultSetMapping( name = "CustomMapping", classes = @ConstructorResult( targetClass = CustomDTO.class, columns = { @ColumnResult(name = "col1", type = String.class), @ColumnResult(name = "col2", type = Integer.class) } ) ) }) @NamedNativeQuery( name = "MyQuery.findCustomData", query = "SELECT col1, col2 FROM my_table", resultSetMapping = "CustomMapping" ) @Entity public class MyEntity { /*...*/ } ``` #### 2. Repository层引用命名查询 在Repository接口中通过`@Query(name = "...")`引用定义好的命名查询: ```java public interface MyRepository extends JpaRepository<MyEntity, Long> { @Query(name = "MyQuery.findCustomData") List<CustomDTO> findCustomData(); } ``` --- ### 替代方案(推荐) #### 方案1:DTO构造函数投影 直接在原生查询中使用构造函数表达式: ```java @Query(value = "SELECT new com.example.CustomDTO(col1, col2) FROM my_table", nativeQuery = false) List<CustomDTO> getData(); ``` #### 方案2:接口投影 定义接口接收部分字段: ```java public interface CustomProjection { String getCol1(); Integer getCol2(); } @Query("SELECT col1 AS col1, col2 AS col2 FROM MyEntity") List<CustomProjection> findProjectedData(); ``` --- ### 对比总结 | 方法 | 适用场景 | 复杂度 | 类型安全 | |---------------------|----------------------------|--------|----------| | `@SqlResultSetMappings` | 复杂字段映射 | 高 | 中 | | DTO构造函数 | 简单字段映射 | 低 | 高 | | 接口投影 | 只读场景 | 最低 | 中 | ---
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值