I cannot return specific properties of an entity class from a repository method.
Exception stacktrace
Resolving exception from handler
[public org.springframework.http.ResponseEntity<java.lang.Object>
org.springframework.data.rest.webmvc.RepositorySearchController.executeSearch
(
org.springframework.data.rest.webmvc.RootResourceInformation,
org.springframework.util.MultiValueMap<java.lang.String, java.lang.Object>,
java.lang.String,
org.springframework.data.rest.webmvc.support.DefaultedPageable,
org.springframework.data.domain.Sort,org.springframework.data.rest.webmvc.Persis
tentEntityResourceAssembler
)
]
: java.lang.IllegalArgumentException: PersistentEntity must not be null!
Entity class
@Entity
@Table(name="reference_data")
@NamedQueries({
@NamedQuery(name="MyTable.findX", query = "SELECT t.name FROM MyTable t WHERE t.catId = 330 ")
})
public class MyTable implements Serializable {
@Id
private Long id;
@Column(name="cat_id")
private Long catId;
@Column(name="name")
private String name;
}
Repository interface
@RepositoryRestResource(collectionResourceRel = "myTables", path = "myTables")
//public interface MyTableDataRepository extends PagingAndSortingRepository<MyTable, Long> { // This didn't work.
public interface MyTableDataRepository extends JpaRepository<MyTable, Long> {
//@Query("SELECT a.name FROM MyTable a WHERE a.catId = 330 ") -- This didn't work.
//@Query(value= "SELECT r.name FROM my_table r ", nativeQuery = true) -- This didn't work either.
@Query("SELECT DISTINCT a.name FROM MyTable a WHERE a.catId = 330 ") // This didn't work either.
List<String> findX(); // This didn't work.
//List<MyDTO> findX(); // DTO with one property: String name.. didn't work either.
}
As you can see, none of the repository methods above works even though they should according to thousands of examples.
The only way I have got it working is as follows:
@Query("SELECT a FROM MyTable a WHERE a.catId = 330") // This WORKS
List<MyTable> findX(); // This WORKS
Technical stack
+-------------------------------+-----------------+
| Dependency | Version |
+-------------------------------+-----------------+
| spring-boot-starter-web | 1.3.5.RELEASE |
| spring-boot-starter-data-jpa | 1.3.5.RELEASE |
| spring-boot-starter-data-rest | 1.3.5.RELEASE |
| HikariCP | 2.4.6 |
| postgresql | 9.3-1102-jdbc41 |
| JDK | 8 |
+-------------------------------+-----------------+
I'd really appreciate any help in getting the query to return only selected properties to work.
This stems from a misunderstanding of what Spring Data REST can do. Whilst you can do what you are describing through direct repository access, you are accessing this method through the automatically exposed REST endpoint, and these only work on mapped classes. This means that any repository methods you expose with Spring Data REST need to return entity types, i.e. those which are annotated with
@Entity
whichjava.lang.String
is not.Whilst you could create a String class wrapper that is also a database entity, as is suggested here this is a terrible approach, and totally unnecessary.
The proper way to achieve what you want is to use projections. You would define a projection interface exposing the fields you want like so:
And then, when you make the request, specify that it is the projection you are interested in.
curl 'http://localhost:8080/mytables?projection=myTableNameProjection'
The results returned will be projections only including the names of the entities. This works equally on individual requests (e.g.
/mytables/1
) or repository search methods.Here is a related question explaining projections, here is the relevant section of the documentation, and here is an example project.
I think the return value should not be
List<String>
butList<Object[]>
.folks, I have tried with a lot of possible work-arounds (tkxs for your inputs), but under spring-data-rest just the whole entity works otherwise I get: 'cause": null message: PersistentEntity must not be null!' .. this needs to be written in some place.. just to avoid a headache you know.
Also, according to spring-data-* documentation we can use @RestResource(exported = false) to hide query methods and entities' fields in HAL.. cuNextChallenge.