You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SpringBoot降至2.3.4.RELEASE时javax.persistence.Tuple.get报错求助

解决SpringBoot 2.3.4.RELEASE中使用javax.persistence.Tuple的访问器方法错误

问题描述

使用javax.persistence.Tuple从PostgreSQL查询数据时,SpringBoot 2.7.5版本运行正常,但降级到2.3.4.RELEASE后抛出以下错误:

java.lang.IllegalArgumentException: Invoked method public abstract java.lang.Object javax.persistence.Tuple.get(java.lang.String) is no accessor method!
at org.springframework.data.projection.Accessor.(Accessor.java:50) ~[spring-data-commons-2.3.4.RELEASE.jar!/:2.3.4.RELEASE]

原因分析

SpringBoot 2.3.4.RELEASE对应的Spring Data Commons版本是2.3.x,这个版本的Accessor类对访问器方法的校验逻辑比较严格:它要求方法符合JavaBean getter规范(比如getXxx()形式、无参数)。而Tuple.get(String)是带参数的方法,不符合该校验规则,因此被判定为非法的访问器方法。

Spring Data后续版本(比如对应SpringBoot2.7的版本)修复了这个问题,能正确识别并处理Tuple类型的方法调用。

解决方案

方案1:改用DTO或接口投影替代Tuple

这是最稳妥的方式,避免直接使用Tuple:

  • DTO方式:创建包含目标字段的DTO类,在JPQL中使用构造函数查询返回该DTO:
    // DTO类
    public class UserDTO {
        private Long id;
        private String name;
    
        public UserDTO(Long id, String name) {
            this.id = id;
            this.name = name;
        }
        // 按需添加getter方法
    }
    
    // Repository中的查询方法
    @Query("select new com.example.dto.UserDTO(u.id, u.name) from User u where u.id = ?1")
    UserDTO findUserById(Long id);
    
  • 接口投影方式:定义包含对应getter方法的接口,Spring Data会自动映射查询结果:
    public interface UserProjection {
        Long getId();
        String getName();
    }
    
    // Repository中的查询方法
    @Query("select u.id as id, u.name as name from User u where u.id = ?1")
    UserProjection findUserProjectionById(Long id);
    

方案2:自定义Repository实现手动处理Tuple

如果必须使用Tuple,可以自定义Repository的实现类,手动处理查询结果:

// 自定义Repository接口
public interface CustomUserRepository {
    Tuple findUserTupleById(Long id);
}

// 实现类
@Repository
public class CustomUserRepositoryImpl implements CustomUserRepository {
    @PersistenceContext
    private EntityManager entityManager;

    @Override
    public Tuple findUserTupleById(Long id) {
        Query query = entityManager.createQuery("select u.id, u.name from User u where u.id = :id", Tuple.class);
        query.setParameter("id", id);
        return (Tuple) query.getSingleResult();
    }
}

// 主Repository继承自定义接口
public interface UserRepository extends JpaRepository<User, Long>, CustomUserRepository {
}

方案3:先修复Gradle依赖冲突

你的build.gradle配置存在依赖冲突问题:

implementation("org.springframework.boot:spring-boot-starter-web:${springBootVersion}")
implementation 'org.springframework.boot:spring-boot-starter-web:2.7.0'

同时声明了两个不同版本的spring-boot-starter-web,会导致依赖混乱,必须统一版本。删掉第二个依赖,全部使用${springBootVersion}(即2.3.4.RELEASE)。

额外说明

不建议单独升级Spring Data Commons版本适配,因为SpringBoot的依赖管理是统一的,单独升级可能引发其他依赖兼容性问题,优先采用前两种方案。

内容的提问来源于stack exchange,提问作者Sanjay Naik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 21:20:28