spring data jpa 利用@Query进行查询

本文详细介绍了Spring Data JPA中@Query注释的使用方法,包括如何定义自定义查询、参数绑定、使用SpEL表达式及与命名查询的区别。同时,展示了如何在实体类上利用@Query实现动态查询,并通过通用接口减少代码冗余。此外,还探讨了利用@Modifying进行更新操作和Spring Data JPA的查询策略配置。

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

介绍@Query注释之前,先看看怎么利用@NamedQuery进行命名查询

1.现在实体类上定义方法已经具体查询语句

@Entity
@NamedQuery(name = "Task.findByTaskName",
  query = "select t from Task t where t.taskName = ?1")
public class Task{

}

2.然后我们继承接口之后,就可以直接用这个方法了,它会执行我们定义好的查询语句并返回结果

public interface TaskDao extends JpaRepository<Task, Long> {
  Task findByTaskName(String taskName);
}

试想一下,如果我们想自己定义执行查询,利用命名查询,显然不行,因为,会在实体类上写很多的@NamedQuery,这种情况的话,我们可以用@Query直接在方法上定义查询语句,例如这样

public interface TaskDao extends JpaRepository<Task, Long> {
  @Query("select t from Task t where t.taskName = ?1")
  Task findByTaskName(String taskName);
}

@Query上面的1代表的是方法参数里面的顺序,除了写hql,我们还可以写sql语句

public interface TaskDao extends JpaRepository<Task, Long> {
  @Query("select * from tb_task t where t.task_name = ?1", nativeQuery = true)
  Task findByTaskName(String taskName);
}

在参数绑定上,我们还可以这样子用

public interface TaskDao extends JpaRepository<Task, Long> {
   @Query("select t from Task t where t.taskName = :taskName and t.createTime = :createTime")
  Task findByTaskName(@Param("taskName")String taskName,@Param("createTime") Date createTime);
}

当然在参数绑定上,我们还可以直写问号

public interface TaskDao extends JpaRepository<Task, Long> {
   @Query("select t from Task t where t.taskName = ? and t.createTime = ?")
  Task findByTaskName(String taskName, Date createTime);
}

再利用SpEL表达式,我们把实体类写成动态的

public interface TaskDao extends JpaRepository<Task, Long> {
   @Query("select t from #{#entityName} t where t.taskName = ? and t.createTime = ?")
  Task findByTaskName(String taskName, Date createTime);
}

这个的作用就是,当俩个实体类都有共同的父类的时候,例如这样

// JPA 基类的标识
@MappedSuperclass
@SuppressWarnings("serial")
public abstract class IdEntity implements Serializable{
    protected Long id;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
}

@Entity
public class Task extends IdEntity{

}

@Entity
public class Project extends IdEntity{

}

然后有一个通用的接口

public interface GenericDao<T> extends JpaRepository<T, ID> { 
  @Query("select t from #{#entityName} t where t.id= ?1")
   public T findById(Long id);   
}

再然后就taskDao和projectDao来继承这个接口,这样子的话,把公用的方法放在通用接口上,就不用重复写方法了。

好,下面再说下,利用@Modifying进行更新

@Modifying
@Query("update Task t set t.taskName = ?1 where t.id = ?2")
int updateTask(String taskName, Long id);

在这里我们说下,spring data jpa的查询策略,spring data jpa可以利用创建方法进行查询,也可以利用@Query注释进行查询,那么如果在命名规范的方法上使用了@Query,那spring data jpa是执行我们定义的语句进行查询,还是按照规范的方法进行查询呢?看下查询策略

查询策略的配置可以在配置query-lookup-strategy,例如这样

    <jpa:repositories base-package="com.liuxg.**.dao"
        repository-impl-postfix="Impl" 
        query-lookup-strategy = "create-if-not-found"
        entity-manager-factory-ref="entityManagerFactory"
        transaction-manager-ref="transactionManager" >
    </jpa:repositories>

他有三种值可以配置

  1. create-if-not-found(默认):如果通过 @Query指定查询语句,则执行该语句,如果没有,则看看有没有@NameQuery指定的查询语句,如果还没有,则通过解析方法名进行查询

  2. create:通过解析方法名字来创建查询。即使有 @Query,@NameQuery都会忽略

  3. use-declared-query:通过执行@Query定义的语句来执行查询,如果没有,则看看有没有通过执行@NameQuery来执行查询,还没有则抛出异常

@Query就先看到这里,下次再了解下怎么拓展spring data jpa 接口,例如我既想用sping data jpa的接口,可是我又想自己定义一些接口,我们把他们合二为一呢??

<think>好的,我需要回答用户关于Spring Data JPA@Query注解支持的所有属性的问题。首先,我应该回忆一下相关的知识,或者查找官方文档来确认属性列表。记得用户提到引用[1]和引用[2],可能需要结合这些内容。 首先,@Query注解主要用于自定义JPQL或原生SQL查询。它的常见属性包括value、nativeQuery、countQuery、name等。用户想了解所有支持的属性,我需要详细列出每个属性的作用及其用法示例。 接下来,我需要确保每个属性的描述准确,并且给出对应的例子,比如设置nativeQuery为true时使用SQL语句。此外,countQuery用于分页查询时自定义计数查询,这也是重要的点。 还要注意是否有其他属性,比如在Spring Data JPA的更新版本中是否有新增的属性。例如,是否有与锁定模式相关的属性,或者flushAutomatically等。需要确认这些信息是否正确,避免遗漏或错误。 然后,结合用户提供的引用内容,引用[1]提到了@Query的基本使用和优先级,引用[2]提到了处理空值的方法。可能需要将这些信息整合到回答中,比如在解释属性时提到如何处理空值的情况。 最后,按照用户的格式要求,使用中文回答,结构清晰,分点列出属性,并给出示例代码。同时,生成相关问题,确保问题与主题相关,帮助用户深入理解。</think>### Spring Data JPA @Query 注解支持的属性列表 Spring Data JPA 的 `@Query` 注解提供了多个属性,用于灵活定义查询逻辑。以下是支持的主要属性及其作用: 1. **value** - **作用**:定义 JPQL 或原生 SQL 查询语句。 - **示例**: ```java @Query("SELECT u FROM User u WHERE u.age > :age") List<User> findByAgeGreaterThan(@Param("age") int age); ``` 2. **nativeQuery** - **作用**:标识是否为原生 SQL 查询(默认为 `false`,即使用 JPQL)。 - **示例**: ```java @Query(value = "SELECT * FROM users WHERE status = 1", nativeQuery = true) List<User> findActiveUsers(); ``` 3. **countQuery** - **作用**:为分页查询(`Pageable`)提供自定义的计数查询(仅在 `nativeQuery = true` 时有效)。 - **示例**: ```java @Query( value = "SELECT * FROM users WHERE department = :dept", countQuery = "SELECT COUNT(*) FROM users WHERE department = :dept", nativeQuery = true ) Page<User> findByDepartment(@Param("dept") String department, Pageable pageable); ``` 4. **name** - **作用**:关联预定义的命名查询(需配合 `@NamedQuery` 使用),优先级低于直接通过 `value` 定义的查询[^1]。 - **示例**: ```java @Query(name = "User.findByEmail") // 引用@NamedQuery定义的查询 List<User> findByEmail(String email); ``` 5. **countProjection** - **作用**(已弃用):早期版本中用于自定义计数查询的投影字段,现更推荐使用 `countQuery` 属性。 --- ### 其他注意事项 - **空值处理**:在动态查询中,若参数可能为 `null`,需结合 `COALESCE` 或 `IS NULL` 条件处理,例如: ```java @Query("SELECT u FROM User u WHERE (:name IS NULL OR u.name = :name)") List<User> findByName(@Param("name") String name); ``` 这种方式可避免因参数为空导致查询语法错误[^2]。 - **修改查询**:若 `@Query` 用于更新/删除操作,需额外添加 `@Modifying` 注解: ```java @Modifying @Query("UPDATE User u SET u.status = :status WHERE u.id = :id") int updateUserStatus(@Param("id") Long id, @Param("status") String status); ``` ---
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值