【发布时间】:2014-11-04 08:19:24
【问题描述】:
我正在尝试让 Spring Data Rest 与我的实体一起工作。我实现了存储库,在请求 localhost:8080 时可以看到可用的列表。
但是,当尝试通过 REST 接口执行任何存储库查询时(例如,通过 localhost:8080/users 执行 findAll()),响应为空。我将问题追溯到以下:
调用 org.springframework.data.jpa.mapping.JpaPersistentEntityImpl.getIdProperty()(在基类 BasicPersistentEntity 中实现的方法)返回 null。调用来自 PersistentEntityResourceAssembler.getSelfLinkFor(..)。然后,空 Id 属性会在堆栈跟踪的下方导致空指针异常,但是除了显示“null ModelAndView”的调试日志之外,此空指针异常永远不会出现在应用程序中。
事实证明,getIdProperty() 返回 null 的唯一原因是因为我没有使用 FIELD 注释,而是使用方法注释。因此@Id 注释应用于 getter getUserId() 而不是归档的 userId。
我不认为这是正确的行为。 JpaPersistentEntityImpl.getIdProperty() 没有正确配置为返回正确的 ID,或者 PersistentEntityResourceAssembler.getSelfLinkFor(..) 应该使用不同的方法来获取 id。除非这些系统不支持使用方法注释的实体,但我一直认为它是有效的 JPA 规范。
任何人都对如何在保持带注释的方法方法(而不是带注释的字段)的同时解决此问题有任何想法。
另外,有谁知道如何更好地配置系统以更好地处理异常,以便此类错误不会如此悄悄地降级?
字段和方法之间的更多不一致:
我还发现必须为所有字段实现 setter 和 getter,以便它们在生成的 json 中呈现。但是对于非基本字段(例如托管 bean),名称是从字段名称而不是属性中获取的(如在基本属性中)。
例如:
@Entity
class User
{
@Id
long Id;
String firstNameField;
String lastNameField;
Account accountField; //a managed bean
long getId() ...
String getFirstName() ...
String getLastName() ....
Account getAccount() ....
}
结果为以下 json:
{
firstName: "..."
lastName: "....."
accountField: ".....link..."
}
不是前两个字段名对应方法名,而托管bean字段对应字段名。
(为简洁起见,我省略了设置器和大多数实体注释,但它们在那里并且正确)
好的,这是一个具体的例子:
/** */
@实体 @Table(名称=“用户”,模式=“汽车”,目录=“”) 公共类用户 {
private int userId;
private String firstName;
private String lastName;
private String password;
private String email;
//todo: Ugh, this is odd...Spring data rest does not seem to render links to ManyToMany properties using method annotation...must add it to the field declaration...removing this from here will result in removing the property from the rest response...needs further investigation
@ManyToMany
@JoinTable (name = "USER_ROLE",
joinColumns = @JoinColumn(updatable = false, insertable = false, name = "USER_ID", referencedColumnName = "USER_ID"),
inverseJoinColumns = @JoinColumn(updatable = false, insertable = false, name = "ROLE_ID", referencedColumnName = "ROLE_ID"))
private Collection<Role> roles;
@Id
@Column (name = "USER_ID")
public int getUserId()
{
return userId;
}
public void setUserId(int inUserId)
{
userId = inUserId;
}
@Basic
@Column (name = "FIRST_NAME")
public String getFirstName()
{
return firstName;
}
public void setFirstName(String inFirstName)
{
firstName = inFirstName;
}
@Basic
@Column (name = "LAST_NAME")
public String getLastName()
{
return lastName;
}
public void setLastName(String inLastName)
{
lastName = inLastName;
}
@Basic
@Column (name = "PASSWORD")
public String getPassword()
{
return password;
}
public void setPassword(String inPassword)
{
password = inPassword;
}
@Override
public boolean equals(Object o)
{
...........
}
@Override
public int hashCode()
{
......
}
@ManyToMany
@JoinTable (name = "USER_ROLE",
joinColumns = @JoinColumn(updatable = false, insertable = false, name = "USER_ID", referencedColumnName = "USER_ID"),
inverseJoinColumns = @JoinColumn(updatable = false, insertable = false, name = "ROLE_ID", referencedColumnName = "ROLE_ID"))
private Collection<Role> getRoles()
{
return roles;
}
private void setRoles(Collection<Role> inRoles)
{
roles = inRoles;
}
@覆盖 公共布尔等于(对象o) { ............ }
@Override
public int hashCode()
{
......
}
}
【问题讨论】:
-
如果您查看源代码,您会发现
@Id注释的放置位置并不重要。它确实对我有用。发布您的具体示例会很有帮助。 非基本字段究竟是什么?
标签: spring spring-data spring-data-jpa spring-data-rest