Spring data JPA: No property XXX found for type XXX
https://blog.csdn.net/weixin_44712778/article/details/115896555
今天开发的时候,遇见一个特别容易被忽视的问题,也是踩坑了,但是我的坑猜的别出心裁,非常少见,也是服了自己。。。
ORM关系映射
Hibernate是一个ORM框架,建立了实体类与数据库表的关系映射,当报错“No property XXX found for type XXX ”时,是指,XXX类没有发现属性XXX。
报错原因有以下三种:
1.接口式方法命名的方法拼写错误
JOPO的属性为:
// JOPO
public class Entity{
...
@Column()
private Long empId;
...
}
// 持久层
@Repository
public interface EntityRepository extends JpaRepository<BannerInfo, String> extends JpaRepository<Entity, String> {
// 明明是findAllByEmpId,一旦这里拼写错误了,就会造成问题
List<Entity> findAllByEmpOOId(String emoId);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
2.JPQL的@Query里面的sql拼写错误
public interface CustomerDao extends JpaRepository<Customer,Long>,JpaSpecificationExecutor<Customer> {
// 如果里面的custName拼写错误,就会抛 No property XXX found for type XXX
@Query(value="from Customer where custName = ?1")
public Customer findCustomer(String custName);
}
- 1
- 2
- 3
- 4
- 5
3.Specification条件查询拼写错误
public void testFind() {
Specification<Entity> spec = new Specification<Entity>() {
public Predicate toPredicate(Root<Entity> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
// 如果此处的entityName拼写错误,就会抛出错误
return cb.equal(root.get("entityName"), "Peter");
}
};
List<LinkMan> list = linkManDao.findAll(spec);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
4.Sort.by拼写错误
DAO层实现的接口JpaRepository提供了findAll查询方法,其中findAll(Sort var1);在查询时可以提供一个排序参数,hibernate可以自动生成SQL语句,自动执行。从而帮你完成查询。
package org.springframework.data.jpa.repository;
@NoRepositoryBean
public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> {
...
List<T> findAll(Sort var1);
...
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
我在使用hibernate的查询语句时,如下:
public List<Item> list() {
//报错原因:这个地方的“create_date”对应的应该是Entity类的属性名,而不是字段名
return itemRepository.findAll(Sort.by("create_date"));
}
- 1
- 2
- 3
- 4
Sort.by的“create_date”对应的应该是Entity类的属性名,而不是字段名。
所以正确的写法应该是return itemRepository.findAll(Sort.by("creationDate"));
源码分析
- findAll方法:执行一个查询语句,获得结果集并返回
Specification:sql描述
public List<T> findAll(Sort sort) {
return this.getQuery((Specification)null, (Sort)sort).getResultList();
}
- 1
- 2
- 3
- getQuery方法:
TypedQuery:查询对象
CriteriaBuilder:查询构造器对象,用于构建查询对象
Root:查询的根对象。个人理解为Root对象连接了实体类和查询描述,将一系列的参数经过加工生成一个类似sql语句的东西,再交给其他方法去执行这个查询。
protected <S extends T> TypedQuery<S> getQuery(@Nullable Specification<S> spec, Class<S> domainClass, Sort sort) {
CriteriaBuilder builder = this.em.getCriteriaBuilder();
CriteriaQuery<S> query = builder.createQuery(domainClass);
Root<S> root = this.applySpecificationToCriteria(spec, domainClass, query);
query.select(root);
if (sort.isSorted()) {
query.orderBy(QueryUtils.toOrders(sort, root, builder));
}
return this.applyRepositoryMethodMetadata(this.em.createQuery(query));
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- toOrders方法:
获取排序对象(可以传给query.orderBy()方法来加工构建查询对象的排序顺序)
错误就是这里的toJpaOrder()方法
public static List<javax.persistence.criteria.Order> toOrders(Sort sort, From<?, ?> from, CriteriaBuilder cb) {
if (sort.isUnsorted()) {
return Collections.emptyList();
}
Assert.notNull(from, "From must not be null!");
Assert.notNull(cb, "CriteriaBuilder must not be null!");
List<javax.persistence.criteria.Order> orders = new ArrayList<>();
for (org.springframework.data.domain.Sort.Order order : sort) {
orders.add(toJpaOrder(order, from, cb));
}
return orders;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- toJpaOrder方法,
这个方法等于是把Order转化为javax.persistence.criteria.Order对象,然后给相关的类去编译。
其中有一个PropertyPath类,大概就是把传入的“createDate”和类的属性对比,找有没有这个类,然后以字符串和属性名比较,如果没有,则会抛出“No property XXX found for type XXX”的错误。
private static javax.persistence.criteria.Order toJpaOrder(Order order, From<?, ?> from, CriteriaBuilder cb) {
// PropertyPath这个类再往底层走我也看不懂了,总之就是会利用
PropertyPath property = PropertyPath.from(order.getProperty(), from.getJavaType());
Expression<?> expression = toExpressionRecursively(from, property);
if (order.isIgnoreCase() && String.class.equals(expression.getJavaType())) {
Expression<String> lower = cb.lower((Expression<String>) expression);
return order.isAscending() ? cb.asc(lower) : cb.desc(lower);
} else {
return order.isAscending() ? cb.asc(expression) : cb.desc(expression);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
示意图
总之除了这个错,绝对就是拼写错误引起的,底层好像有一个代理会根据你的拼写去JOPO类的属性,如果这个属性没找到,就会报这个错,仔细检查你的字段拼写就完事了。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)
2022-03-22 Vue2.0 no-side-effects-in-computed-properties WARNING处理 点击原文查看动态效果
2022-03-22 vue中select的使用以及select设置默认选中
2022-03-22 vue中 关于select选项的写法 有三种情况 ①.写在HTML中,②.写在JS一个数组中,③.通过接口去获取得到,
2022-03-22 解决html页面或vue页面初始进入时页面闪烁。出现{{}}数据的现象
2022-03-22 springmvc的controller方法不指定method时可以GET或POST提交
2022-03-22 springboot 在controller层获取Post请求中request.getInputStream的值
2022-03-22 controller 接收Post传递数据