SpringDataJpa基础篇5:@Query与@Modifying注解使用

本文详细介绍JPA中@Query注解的使用,包括基本查询、参数传递、模糊查询、本地SQL查询及@Modifying注解的使用,适用于希望深入了解JPA查询机制的开发者。

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

 

1、@Query注解

1.1、@Query注解源码

@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE })
@QueryAnnotation
@Documented
public @interface Query {
//定义一个JPQL语句
	String value() default "";
	String countQuery() default "";	
	String countProjection() default "";
//是否开启本地sql语句查询,默认是false
	boolean nativeQuery() default false;
	String name() default "";
	String countName() default "";
}

 1.2、JPQL语句基本查询

后续所有操作的例子都是参考这个实体类

@Entity
@Table(name="tb_label")
public class Label implements Serializable {
    @Id
    private String id;//
    private String labelname;//标签名称
    private String state;//状态
    private Long count;//使用数量
    private Long fans;//关注数
    private String recommend;//是否推荐
    public Label() {
    }

    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getLabelname() {
        return labelname;
    }
    public void setLabelname(String labelname) {
        this.labelname = labelname;
    }
    public String getState() {
        return state;
    }
    public void setState(String state) {
        this.state = state;
    }
    public Long getCount() {
        return count;
    }
    public void setCount(Long count) {
        this.count = count;
    }
    public Long getFans() {
        return fans;
    }
    public void setFans(Long fans) {
        this.fans = fans;
    }
    public String getRecommend() {
        return recommend;
    }
    public void setRecommend(String recommend) {
        this.recommend = recommend;
    }

    @Override
    public String toString() {
        return "Label{" +
                "id='" + id + '\'' +
                ", labelname='" + labelname + '\'' +
                ", state='" + state + '\'' +
                ", count=" + count +
                ", fans=" + fans +
                ", recommend='" + recommend + '\'' +
                '}';
    }
}
//dao层代码
public interface LabelDao extends JpaRepository<Label,String> {
    //使用@Query注解可以自定义JPQL语句以实现更灵活的查询
    @Query("SELECT l from Label l where l.id=(select max(l2.id) from Label l2) ")
    Label getMaxId();
}

//测试代码
@RunWith(SpringRunner.class)
@SpringBootTest(classes = BaseApplication.class)
public class JpaTest {
 @Autowired
 private LabelDao labelDao;
@Test
 public void testQuery(){
        Label label = labelDao.getMaxId();
        System.out.println("-----------label-------------"+label.toString());
    }
}

1.3、@Query注解传递参数查询

//**************************************dao层代码**************************************
public interface LabelDao extends JpaRepository<Label,String> {

    /**
     * 为@Query注解传递参数的方式1:使用占位符,且传递参数必须按照指定的顺序
     * @return
     */
    @Query("SELECT l from Label l where l.labelname=?1 and l.state=?2")
    List<Label> testQueryAnnotationParams1(String labelname,String state);

    /**
     * 为@Query注解传递参数的方式2:使用命名参数的方式,配合@Param注解一起使用
    */
    @Query("SELECT l from Label l where l.labelname=:labelname and l.state=:state")
    List<Label> testQueryAnnotationParams2(@Param("state") String state, @Param("labelname") String name);

}
//******************************测试代码**********************************************
@RunWith(SpringRunner.class)
@SpringBootTest(classes = BaseApplication.class)
public class JpaTest {
    @Autowired
    private LabelDao labelDao;
 /**
     * @Query注解传递参数的方式1:使用占位符
     */
    @Test
    public void testQueryAnnotationParam1(){
        List<Label> list = labelDao.testQueryAnnotationParams1("java", "1");
        list.stream().forEach(label -> {
            System.out.println("*****"+label.toString());
        });
    }

    /**
     * @Query注解传递参数的方式2:使用命名参数的方式,配合@Param注解一起使用
     */
    @Test
    public  void testQueryAnnotationParams2(){
        List<Label> list = labelDao.testQueryAnnotationParams2("1", "php");
        list.stream().forEach(label -> {
            System.err.println("*****"+label.toString());
        });
    }

}

 

1.4、@Query注解中Like模糊查询

//***********************************以下是dao代码*********************************************
public interface LabelDao extends JpaRepository<Label,String> {

    /**
     *  @Query注解Like模糊查询1: @Query不写百分号%,但在调用方法时需要使用
     */
    @Query("SELECT l from Label l where l.labelname like ?1 or l.state=?2")
    List<Label> testQueryAnnotationLikeParams1(String labelname,String state);
    /**
     *  @Query注解Like模糊查询2: @Query写百分号%,但在调用方法时不用写
     */
    @Query("SELECT l from Label l where l.labelname like %?1% or l.state=?2")
    List<Label> testQueryAnnotationLikeParams2(String labelname,String state);

    /**
     *  @Query注解Like模糊查询3,使用命名方式结合@Param注解
     */
    @Query("SELECT l from Label l where l.labelname like %:labelname% or l.state=:state")
    List<Label> testQueryAnnotationLikeParams3(@Param("state") String state,@Param("labelname") String name);
}
//***********************************以下是测试代码*********************************************
@RunWith(SpringRunner.class)
@SpringBootTest(classes = BaseApplication.class)
public class JpaTest {
    @Autowired
    private LabelDao labelDao;

 /**
     * 使用like模糊查询 @Query中不写百分号%,但在调用方法时需要使用
     */
    @Test
    public void testQueryAnnotationLikeParams1(){
        List<Label> list = labelDao.testQueryAnnotationLikeParams1("%java%", "1");
        list.stream().forEach(label -> {
            System.err.println("*****"+label.toString());
        });
    }
    /**
     * 使用like模糊查询 @Query中写百分号%,但在调用方法时不用写
     */
    @Test
    public void testQueryAnnotationLikeParams2(){
        List<Label> list = labelDao.testQueryAnnotationLikeParams2("java", "1");
        list.stream().forEach(label -> {
            System.err.println("*****"+label.toString());
        });
    }
    @Test
    public void testQueryAnnotationLikeParams3(){
        List<Label> list = labelDao.testQueryAnnotationLikeParams3("1", "php");
        list.stream().forEach(label -> {
            System.err.println("*****"+label.toString());
        });
    }
}

1.5、@Query注解本地SQL语句查询

//*********************************dao层代码*****************************************
public interface LabelDao extends JpaRepository<Label,String> {

    /**
     * 原生的sql语句查询
     * nativeQuery =true表示启用本地sql语句查询
     * @return
     */
    @Query(value = "select count(id) from tb_label",nativeQuery =true )
    long getCount();
}

//**********************************测试代码**********************************************
@RunWith(SpringRunner.class)
@SpringBootTest(classes = BaseApplication.class)
public class JpaTest {
    @Autowired
    private LabelDao labelDao;
   @Test
    public void getCount(){
        long count = labelDao.getCount();
        System.err.println("------------:"+count);
    }
}

2、@Modifying注解

         在springdatajpa中如果想使用update和delete操作必须使用@Query注解和@Modifying注解,使用@Modifying注解就表示操作一个更新或者删除操作。

         可以通过定义的JPQL完成update和delete操作,注意JPQL不支持使用insert。在@Query注解中编写JPQL语句,但必须使用@Modifying注解进行修饰,用来通知SpringData,这是一个update和delete操作。

【注意】在update或delete操作需要使用事物,此时需要我们定义service层,在server层的方法上添加事物操作。默认情况下,SpringData的每个方法上都有事物,但是这个默认事物是只读事物,它不能完成修改操作.

//*********************************DAO层************************************************
public interface LabelDao extends JpaRepository<Label,String> {
    /**
     * 可以通过定义的JPQL完成update和delete操作,注意JPQL不支持使用insert。
     * 在@Query注解中编写JPQL语句,但必须使用@Modifying注解进行修饰,用来通知SpringData,这是一个update和delete操作。
     */
    @Modifying
    @Query("update Label label set label.labelname=:name where label.id=:id")
    void updateData(@Param("id") String id,@Param("name")String name);

}

//******************************service层***************************************************
@Service
public class LabelService {
    @Autowired
    private LabelDao labelDao;
//注意更新方法中使用了事物注解
    @Transactional   
    public void updateNameById(String id,String name){
        labelDao.updateData(id,name);
    }
}

//************************************测试*********************************************
@RunWith(SpringRunner.class)
@SpringBootTest
public class Test2 {
    @Autowired
    private LabelService labelService;
    @Test
    public void update(){
        labelService.updateNameById("","java----");
    }
}



 

<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); ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值