Spring data JPA: No property XXX found for type XXX 根据方法名字中属性未找到 映射数据库实体Entity中的属性 可能不规范命名或者方法名字写错 建议小驼峰命名不带下划线

发布时间 2023-03-22 21:13:59作者: sunny123456

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"));

源码分析

  1. findAll方法:执行一个查询语句,获得结果集并返回
    Specification:sql描述
public List<T> findAll(Sort sort) {
        return this.getQuery((Specification)null, (Sort)sort).getResultList();
}
  • 1
  • 2
  • 3
  1. 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
  1. 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
  1. 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类的属性,如果这个属性没找到,就会报这个错,仔细检查你的字段拼写就完事了。