Pageable自动转小驼峰引发JPA属性定位失败问题求助
我的实体类UserFlight采用大驼峰命名属性(例如MessageSequenceID),但使用PageRequest.of()创建Pageable时,Sort.by()指定的属性会被自动转换为小驼峰格式,触发以下错误:
Unable to locate Attribute with the given name [messageSequenceID] on this ManagedType [com.loader.batch.IF.entity.UserFlight]
相关代码
实体类UserFlight代码
package com.loader.batch.IF.entity; import jakarta.persistence.*; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; @Entity @Table(name = "data_flight") public class UserFlight { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "MessageSequenceID", nullable = false) private Long MessageSequenceID; @Column(name = "MessageType", length = 30) private String MessageType; @Column(name = "ServiceType", length = 30) private String ServiceType; @Column(name = "OperationMode", length = 30) private String OperationMode; @Column(name = "SendDateTime", length = 30) private String SendDateTime; @Column(name = "CreateDateTime", length = 30) private String CreateDateTime; public UserFlight( Long MessageSequenceID, String MessageType, String ServiceType, String OperationMode, String SendDateTime, String CreateDateTime) { this.MessageSequenceID = MessageSequenceID; this.MessageType = MessageType; this.ServiceType = ServiceType; this.OperationMode = OperationMode; this.SendDateTime = SendDateTime; this.CreateDateTime = CreateDateTime; } public Long getMessageSequenceID() { return MessageSequenceID; } public void setMessageSequenceID(Long messageSequenceID) { MessageSequenceID = messageSequenceID; } public String getMessageType() { return MessageType; } public void setMessageType(String messageType) { MessageType = messageType; } public String getServiceType() { return ServiceType; } public void setServiceType(String serviceType) { ServiceType = serviceType; } public String getOperationMode() { return OperationMode; } public void setOperationMode(String operationMode) { OperationMode = operationMode; } public String getSendDateTime() { return SendDateTime; } public void setSendDateTime(String sendDateTime) { SendDateTime = sendDateTime; } public String getCreateDateTime() { return CreateDateTime; } public void setCreateDateTime(String createDateTime) { CreateDateTime = createDateTime; } }
服务类代码
Pageable pageable = PageRequest.of(req.getPage(), req.getLimit(), Sort.by("MessageSequenceID")); UserFlight userFlight = new UserFlight(); userFlight.setStatus(req.getSearch()); Example<UserFlight> example = Example.of(userFlight, SEARCH_CONDITIONS_MATCH_ANY); var flightData = flightRepository.findAll(example, pageable);
抛出异常
org.springframework.dao.InvalidDataAccessApiUsageException: Unable to locate Attribute with the given name [messageSequenceID] on this ManagedType [com.loader.batch.IF.entity.UserFlight]
我已经尝试在application.properties中配置spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl,并将Sort.by()参数修改为messageSequenceID,但问题依旧存在。
问题根源
JPA遵循JavaBean规范解析实体属性:你的实体类属性是大驼峰开头(MessageSequenceID),但对应的getter方法是getMessageSequenceID(),按照规范,这个getter对应的属性名应该是messageSequenceID(小驼峰开头)。这就造成了JPA识别的属性名和你定义的实际属性名不匹配,排序时无法找到正确的属性。
解决方法
方法1:修正实体类属性命名(推荐)
遵循JavaBean规范,将实体类的属性改为小驼峰开头,同时保持@Column的name属性对应数据库列名,这样JPA就能正确识别属性:
@Column(name = "MessageSequenceID", nullable = false) private Long messageSequenceID; // 修改为小驼峰开头 // getter和setter保持不变,符合JavaBean规范 public Long getMessageSequenceID() { return messageSequenceID; } public void setMessageSequenceID(Long messageSequenceID) { this.messageSequenceID = messageSequenceID; }
修改后,使用Sort.by("messageSequenceID")即可正常排序。
方法2:使用SQL列名直接排序(无需修改实体类)
如果无法修改实体类,可以使用JpaSort.unsafe()直接指定数据库列名进行排序:
// 直接用数据库列名排序 Pageable pageable = PageRequest.of(req.getPage(), req.getLimit(), JpaSort.unsafe("MessageSequenceID"));
内容的提问来源于stack exchange,提问作者Famz Testa

