Repository 方法只能返回整个实体而不是某些属性 [英] Repository method only works returning the whole entity instead of some properties
问题描述
我无法从存储库方法返回实体类的特定属性.
<块引用>异常堆栈跟踪
从处理程序中解决异常[公共 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,org.springframework.data.rest.webmvc.support.DefaultedPageable,org.springframework.data.domain.Sort,org.springframework.data.rest.webmvc.Persis帐篷实体资源组装器)]: java.lang.IllegalArgumentException: PersistentEntity 不能为空!
<块引用>
实体类
@Entity@Table(name="reference_data")@NamedQueries({@NamedQuery(name="MyTable.findX", query = "SELECT t.name FROM MyTable t WHERE t.catId = 330 ")})公共类 MyTable 实现了 Serializable {@Id私人长ID;@Column(name="cat_id")私人长猫ID;@列(名称=名称")私人字符串名称;}
<块引用>
存储库界面
@RepositoryRestResource(collectionResourceRel = "myTables", path = "myTables")//公共接口MyTableDataRepository扩展PagingAndSortingRepository{//这没有用.公共接口 MyTableDataRepository 扩展 JpaRepository{//@Query("SELECT a.name FROM MyTable a WHERE a.catId = 330 ") -- 这不起作用.//@Query(value= "SELECT r.name FROM my_table r ", nativeQuery = true) -- 这也不起作用.@Query("SELECT DISTINCT a.name FROM MyTable a WHERE a.catId = 330 ")//这也不起作用.列表<字符串>findX();//这没有用.//列表findX();//带有一个属性的 DTO:字符串名称.. 也不起作用.}
如您所见,即使根据数千个示例,上述存储库方法都应该有效.
我让它工作的唯一方法如下:
@Query("SELECT a FROM MyTable a WHERE a.catId = 330")//这有效列表findX();//这有效
<块引用>
技术栈
+-------------------------------+-----------------+|依赖 |版本 |+-------------------------------+-----------------+|spring-boot-starter-web |1.3.5.发布 ||spring-boot-starter-data-jpa |1.3.5.发布 ||spring-boot-starter-data-rest |1.3.5.发布 ||HikariCP |2.4.6 ||PostgreSQL |9.3-1102-jdbc41 ||JDK |8 |+-------------------------------+-----------------+
如果您能帮助查询仅返回选定的属性,我将不胜感激.
这源于对 Spring Data REST 可以做什么的误解.虽然您可以通过直接存储库访问来执行您所描述的操作,但您正在通过自动公开的 REST 端点访问此方法,并且这些仅适用于映射类.这意味着您使用 Spring Data REST 公开的任何存储库方法都需要返回实体类型,即那些用 @Entity
注释的实体类型,而 java.lang.String
不是.
虽然您可以创建一个 String 类包装器,它也是一个数据库实体,正如这里所建议的 这是一种糟糕的方法,完全没有必要.
实现您想要的目标的正确方法是使用投影.您将定义一个投影界面,像这样公开您想要的字段:
@Projection(name = "myTableNameProjection", types = MyTable.class)公共接口 MyTableNameProjection {字符串 getName();}
然后,当您提出请求时,请指明它是您感兴趣的投影.
curl 'http://localhost:8080/mytables?projection=myTableNameProjection'
返回的结果将是仅包含实体名称的投影.这同样适用于单个请求(例如 /mytables/1
)或存储库搜索方法.
这里 是一个解释投影的相关问题,这里是文档的相关部分,这里 是一个示例项目.
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
which java.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:
@Projection(name = "myTableNameProjection", types = MyTable.class)
public interface MyTableNameProjection {
String getName();
}
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.
这篇关于Repository 方法只能返回整个实体而不是某些属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!