Spring Data Rest嵌入式实体的投影

6
假设我有以下实体:
@Entity
public class Registration {

    @ManyToOne
    private Student student;
    //getters, setters
}

@Entity
public class Student {

    private String id;
    private String userName;
    private String name;
    private String surname;
    //getters, setters
}

@Projection(name="minimal", types = {Registration.class, Student.class})
public interface RegistrationProjection {

    String getUserName();
    Student getStudent();

}

我正试图创建以下JSON表示形式,这样当我使用http://localhost:8080/api/registrations?projection=minimal时,我不需要所有的用户数据一起返回:
{
  "_links": {
    "self": {
      "href": "http://localhost:8080/api/registrations{?page,size,sort,projection}",
    }
  },
  "_embedded": {
    "registrations": [
      {
        "student": {
          "userName": "user1"
        }
      }
    ],
    "_links": {
      "self": {
        "href": "http://localhost:8080/api/registrations/1{?projection}",
      }
    }
  }
}

然而,我创建的投影中出现了异常(如果不使用getUserName()语句,则可以正常工作)。很明显我以错误的方式定义了接口...但是正确的方法是什么呢?

编辑:异常如下

Invalid property 'userName' of bean class [com.test.Registration]: 
Could not find field for property during fallback access! (through reference chain: org.springframework.hateoas.PagedResources["_embedded"]
->java.util.UnmodifiableMap["registrations"]->java.util.ArrayList[0]->org.springframework.data.rest.webmvc.json.["content"]
-&gt;$Proxy119[&quot;userName&quot;])</div></body></html>

你可以分享一下你遇到了哪个异常吗? - Erik Pragt
1个回答

12

异常信息说userName不是Registration实体的成员,这就是失败的原因。但我想你已经理解了这一点。

首先,如果你只想暴露其投影以供Registration使用,你应该先更改以下行:

@Projection(name="minimal", types = {Registration.class, Student.class})

通过设置 types = {Registration.class, Student.class},您要求Spring Data Rest对Registration.classStudent.class应用投影。这可能会导致一些问题,因为根据类型,您不应该拥有相同的成员/方法。实际上,types必须共享一个公共祖先。

否则,对于主要问题,您可以尝试虚拟投影下面的内容(我没有在您的示例中尝试过,但应该可以运行,希望如此):

@Projection(name="minimal", types = {Registration.class})
public interface RegistrationProjection {

    @Value("#{target.getStudent().getUserName()}")
    String getUserName();
}

我不知道你是否熟悉SPeL,但先前的代码只是创建了一个类似于this.getStudent().getUserName()getUserName方法,因为target绑定在实例对象上(请参考文档)。


你似乎对投影有一定的了解。这可能是一个奇怪的问题,但你知道是否可以在不编写自定义控制器的情况下将投影添加到POST或PATCH请求中吗?我们的API由Spring生成。 - Markvds
很抱歉,@user1758777,我已经好几年没有使用Spring data rest了,所以无法帮助你。但我认为仅针对POST或PATCH进行投影是不太可能的。我建议你在Stack上开一个新的问题或者在Spring data rest Gitter上提问。 - Kakawait

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接