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

Spring Batch报错:WsaCtpImcrAllocation无id属性问题求助

Spring Batch Reader步骤报错:PropertyReferenceException: No property id found for type WsaCtpImcrAllocation!

报错信息

exitCode=FAILED;exitDescription=org.springframework.data.mapping.PropertyReferenceException: No property id found for type WsaCtpImcrAllocation!

问题场景

开发批量任务实现数据库内数据克隆,任务包含多步骤,执行Reader步骤时触发上述错误。代码中明确使用sandboxId作为查询条件,WsaCtpImcrAllocation是CtpImcrAllocation的子类,二者字段大部分一致。

相关代码

Job配置类

private WsaSandbox sandbox;
...
@Bean
@StepScope
public RepositoryItemReader<WsaCtpImcrAllocation> wsaCtpImcrAllocationCloneReader(WsaCtpImcrAllocationRepo wsaCtpImcrAllocationRepo){
    RepositoryItemReader<WsaCtpImcrAllocation> wsaCtpImcrAllocationCloneRepositoryItemReader = new RepositoryItemReader<>();
    wsaCtpImcrAllocationCloneRepositoryItemReader.setRepository(wsaCtpImcrAllocationRepo);
    wsaCtpImcrAllocationCloneRepositoryItemReader.setMethodName("findAllBySandboxId");
    wsaCtpImcrAllocationCloneRepositoryItemReader.setArguments(Arrays.asList(sandbox));
    wsaCtpImcrAllocationCloneRepositoryItemReader.setSort(sortMap);
    return wsaCtpImcrAllocationCloneRepositoryItemReader;
}

Writer类

@StepScope
public class CloneWsaCtpImcrAllocationCustomItemWriter implements ItemWriter<WsaCtpImcrAllocation>, StepExecutionListener{
    private static final Logger log = LogManager.getLogger(CloneWsaTradeWhatIfCustomItemWriter.class);
    @Autowired
    WsaCtpImcrAllocationRepo wsaCtpImcrAllocationRepo;
    @Autowired
    WsaSandboxRepo wsaSandboxRepo;
    private WsaSandbox newSandbox;
    @Override
    public void write(List<? extends WsaCtpImcrAllocation> items) throws Exception {
        try {
            items.stream().forEach(allocation->wsaCtpImcrAllocationRepo.saveCopy(allocation, newSandbox));
        } catch (Exception e) {
            log.catching(e);
        }
    }
    @Override
    public ExitStatus afterStep(StepExecution stepExecution) {
        return null;
    }
    @Override
    public void beforeStep(StepExecution stepExecution) {
        newSandbox = (WsaSandbox) stepExecution.getJobExecution().getExecutionContext().get("newSandbox");
    }
}

Repository接口

@Repository
public interface WsaCtpImcrAllocationRepo extends PagingAndSortingRepository<WsaCtpImcrAllocation, CtpImcrAllocationId>, WsaCtpImcrAllocationRepoCustom {
    List<WsaCtpImcrAllocation> findAllBySandboxId(WsaSandbox sandboxId);
    Page<WsaCtpImcrAllocation> findAllBySandboxId(WsaSandbox sandboxId, Pageable pageable);
...
}

子类实体WsaCtpImcrAllocation

@Entity
@Table(name = "WSA_CTP_IMCR_ALLOCATION")
public class WsaCtpImcrAllocation extends CtpImcrAllocation{
    @ManyToOne
    @JoinColumn(name = "SANDBOX_ID", referencedColumnName = "ID", nullable = true)
    @JsonProperty
    @JsonView(ExtractionJsonView.FullWithChildren.class)
    private WsaSandbox sandboxId;
    @Column(name = "CUSTOM")
    @JsonProperty
    @JsonView(ExtractionJsonView.Full.class)
    private Boolean isCustom = false ;
    ....
}

父类实体CtpImcrAllocation

@Entity
@Table(name = "CTP_IMCR_ALLOCATION")
@Inheritance (strategy = InheritanceType.TABLE_PER_CLASS)
@IdClass(CtpImcrAllocationId.class)
public class CtpImcrAllocation {
    @Column(name = "BUSINESS_DATE")
    @Id
    @JsonProperty
    @JsonView(ExtractionJsonView.Full.class)
    @Temporal(TemporalType.DATE)
    private Date businessDate;
    @Column(name = "PERIMETER")
    @Id
    @JsonProperty
    @JsonView(ExtractionJsonView.Full.class)
    private String perimeter;
    @Column(name="IDENTIFIER")
    @Id
    @JsonProperty
    @JsonView(ExtractionJsonView.Full.class)
    private String identifier;
    ...
}

复合主键类CtpImcrAllocationId

public class CtpImcrAllocationId implements Serializable{
    private static final long serialVersionUID = 9063822398839581588L;
    private Date businessDate;
    private String perimeter;
    private String identifier;
    public Date getBusinessDate() {
        return businessDate;
    }
    public void setBusinessDate(Date businessDate) {
        this.businessDate = businessDate;
    }
    public String getPerimeter() {
        return perimeter;
    }
    public void setPerimeter(String perimeter) {
        this.perimeter = perimeter;
    }
    public String getIdentifier() {
        return identifier;
    }
    public void setIdentifier(String identifier) {
        this.identifier = identifier;
    }
}

问题原因

RepositoryItemReader默认会尝试使用实体的id属性作为分页排序的默认字段,但你的实体WsaCtpImcrAllocation继承自父类,使用的是复合主键(通过@IdClass定义),不存在单一的id属性,因此Spring Data无法找到对应属性,抛出PropertyReferenceException。

解决方案

  1. 显式指定排序字段:确保sortMap中配置的是实体实际存在的属性,比如父类的复合主键字段或子类的sandboxId,示例如下:
Map<String, Sort.Direction> sortMap = new HashMap<>();
// 使用复合主键字段排序
sortMap.put("businessDate", Sort.Direction.ASC);
sortMap.put("perimeter", Sort.Direction.ASC);
sortMap.put("identifier", Sort.Direction.ASC);
  1. 检查分页查询逻辑:确认Repository中带Pageable参数的findAllBySandboxId方法能正确接收排序参数,确保排序字段与实体属性一致。

内容的提问来源于stack exchange,提问作者lorenzo_.aiello

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 09:36:00