Spring Data MongoDB中带下划线数据模型变量的使用及报错处理
解决Spring Data MongoDB聚合时的PropertyReferenceException问题
这个问题我之前也碰到过,咱们来一步步拆解原因和解决方案:
错误原因分析
你看到的org.springframework.data.mapping.PropertyReferenceException: No property person found for type Employee!,本质是Spring Data MongoDB的属性解析机制导致的:
Spring Data默认会把下划线_当成嵌套属性的分隔符,当你在聚合分组里写"person_Type"时,它会错误地解析为要访问person属性下的Type属性,但你的Employee类里根本没有person这个属性,所以直接抛出了找不到属性的异常。
解决方案
方案1:用方法引用替代字符串字段名(推荐,更安全)
这种方式完全避免字符串字段名的解析问题,同时还能享受编译时检查的好处。
步骤1:给Employee类添加getter方法
你的Employee类里除了emp_id是public,其他字段都是private,Spring需要通过getter来识别属性:
@Document(collection = "employee") public class Employee { @Id public long emp_id; private String work_Geography; private String work_Country; private String work_Location; private String customer; private String project_Location; private String person_Type; // 添加以下getter方法 public String getCustomer() { return customer; } public String getPerson_Type() { return person_Type; } public String getProject_Location() { return project_Location; } // 其他字段的getter可以按需添加 }
步骤2:修改聚合代码为方法引用形式
TypedAggregation<Employee> employeeAggregation = Aggregation.newAggregation(Employee.class, // 用方法引用指定分组字段 Aggregation.group(Employee::getCustomer, Employee::getPerson_Type, Employee::getProject_Location) .count().as("total"), Aggregation.project("customer", "person_Type", "project_Location", "total"), // 排序也改用方法引用 Aggregation.sort(Direction.ASC, Employee::getCustomer, Employee::getPerson_Type, Employee::getProject_Location) ); AggregationResults<Employee> results = mongoTemplate.aggregate(employeeAggregation, Employee.class);
方案2:使用普通Aggregation而非TypedAggregation
如果不想修改实体类,可以直接绕过Spring的属性解析,用集合名称代替实体类类型,直接使用MongoDB的原始字段名:
// 不使用TypedAggregation,直接创建普通Aggregation Aggregation aggregation = Aggregation.newAggregation( Aggregation.group("customer","person_Type","project_Location").count().as("total"), Aggregation.project("customer","person_Type","project_Location", "total"), Aggregation.sort(Direction.ASC,"customer" ,"person_Type","project_Location") ); // 第三个参数指定结果映射的实体类 AggregationResults<Employee> results = mongoTemplate.aggregate(aggregation, "employee", Employee.class);
方案3:修改实体类属性为Java驼峰命名规范(长期维护推荐)
从Java编码规范来说,属性名应该用驼峰形式而非下划线,这样能从根源避免这类解析问题。
步骤1:修改实体类属性名并指定MongoDB字段映射
@Document(collection = "employee") public class Employee { @Id public long empId; private String workGeography; private String workCountry; private String workLocation; private String customer; // 用@Field指定MongoDB中存储的下划线字段名 @Field("project_Location") private String projectLocation; @Field("person_Type") private String personType; // 对应的getter和setter方法(驼峰形式) public String getCustomer() { return customer; } public String getProjectLocation() { return projectLocation; } public String getPersonType() { return personType; } // 其他字段的getter/setter }
步骤2:修改聚合代码使用驼峰属性名
TypedAggregation<Employee> employeeAggregation = Aggregation.newAggregation(Employee.class, Aggregation.group("customer","personType","projectLocation").count().as("total"), Aggregation.project("customer","personType","projectLocation", "total"), Aggregation.sort(Direction.ASC,"customer" ,"personType","projectLocation") ); AggregationResults<Employee> results = mongoTemplate.aggregate(employeeAggregation, Employee.class);
内容的提问来源于stack exchange,提问作者JokerBean
相关产品推荐
相关产品推荐

