javaspringspring-data-jpajpa-criteria

JPA - How to query using Specification and @EmbeddedId?


I'm using a JPA query that uses a specification to retrieve entities. When I execute the query, I'm getting the error:

org.springframework.data.mapping.PropertyReferenceException: No property name found for type Task!

I've looked at the answers to similar questions that have been asked on this site previously & tried to model my code to follow the patterns that were recommended but the code is still failing.

When I step through the code with a debugger, the expanded path in the criteria builder is returning the embedded ID class, but when the specification is actually used in the query it looks like the attribute is being applied to the base entity class.

Am I missing something obvious?

Here is the entity class:

@Entity
@Table(name = "TASKS")
public class Task implements Serializable {

    @EmbeddedId
    private TaskId id;

    ...more attributes, getters and setters
}

Here is the embedded ID entity class:

@Embeddable
public class TaskId implements Serializable {

    @Column(name = "NAME", length = 100)
    private String name;

    ...more attributes, getters and setters
}

Here is the specification builder that matches on the embedded id 'name' attribute:

public class HasTaskNameSpec {

    private HasTaskNameSpec() {
    }

    public static Specification<Task> equals(String name) {
        return (root, query, criteriaBuilder) -> {
            return criteriaBuilder.equal(root.get("id").get("name"), taskName);
        };
    }

}

The query is executed on the repository as follows:

List<Task> results = taskRepository.findAll(HasTaskNameSpec.equals("foo"));

The repository itself is very simple:

public interface TaskRepository extends JpaRepository<Task, TaskId>, JpaSpecificationExecutor<Task> {
   List<Task> findByIdName(String name);
   Page<Task> findByIdName(String name, Pageable page);    
}

** EDIT added methods to repository as was suggested below **


Solution

  • Take a look at this link which has a similar query.

    EmbbededId Lookup

    The final answer suggests that you can add a method to your TaskRepository thus.

    public interface TaskRepository extends JpaRepository<Task, TaskId>, JpaSpecificationExecutor<Task> {
       public List<Task> findByIdName(String name);
    }