如何在POST json中传递@EmbeddedId在spring中-boot data rest
How to pass @EmbeddedId in POST json in spring-boot data rest
我使用 Spring 引导数据 REST 构建了一个 REST API。我正在使用 embeddedId 并且还实现了 BackendIdConverter。
下面是我的 Embeddable class
@Embeddable
public class EmployeeIdentity implements Serializable {
@NotNull
@Size(max = 20)
private String employeeId;
@NotNull
@Size(max = 20)
private String companyId;
public EmployeeIdentity() {}
public EmployeeIdentity(String employeeId, String companyId) {
this.employeeId = employeeId;
this.companyId = companyId;
}
public String getEmployeeId() {
return employeeId;
}
public void setEmployeeId(String employeeId) {
this.employeeId = employeeId;
}
public String getCompanyId() {
return companyId;
}
public void setCompanyId(String companyId) {
this.companyId = companyId;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
EmployeeIdentity that = (EmployeeIdentity) o;
if (!employeeId.equals(that.employeeId)) return false;
return companyId.equals(that.companyId);
}
@Override
public int hashCode() {
int result = employeeId.hashCode();
result = 31 * result + companyId.hashCode();
return result;
}
}
这是我的员工模型
@Entity
@Table(name = "employees")
public class Employee {
@EmbeddedId
private EmployeeIdentity id;
@NotNull
@Size(max = 60)
private String name;
@NaturalId
@NotNull
@Email
@Size(max = 60)
private String email;
@Size(max = 15)
@Column(name = "phone_number", unique = true)
private String phoneNumber;
public Employee() {}
public Employee(EmployeeIdentity id, String name, String email, String phoneNumber) {
this.id = id;
this.name = name;
this.email = email;
this.phoneNumber = phoneNumber;
}
public EmployeeIdentity getId() {
return id;
}
public void setId(EmployeeIdentity id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
}
并使用我的嵌入 ID 而不是合格的 class 名称正确生成资源链接
@Component
public class EmployeeIdentityIdConverter implements BackendIdConverter {
@Override
public Serializable fromRequestId(String id, Class<?> aClass) {
String[] parts = id.split("_");
return new EmployeeIdentity(parts[0], parts[1]);
}
@Override
public String toRequestId(Serializable source, Class<?> aClass) {
EmployeeIdentity id = (EmployeeIdentity) source;
return String.format("%s_%s", id.getEmployeeId(), id.getCompanyId());
}
@Override
public boolean supports(Class<?> type) {
return Employee.class.equals(type);
}
}
这是我的存储库代码
@RepositoryRestResource(collectionResourceRel = "employees", path = "employees")
public interface EmployeeRepository extends PagingAndSortingRepository<Employee, EmployeeIdentity> {
}
这适用于 GET 请求,但我需要能够 POST。我注意到的第一件事是当我用 json
做 POST
{
"id": {
"employeeId": "E-267",
"companyId": "D-432"
},
"name": "Spider Man",
"email": "spman@somedomain.com",
"phoneNumber": "+91-476253455"
}
这行不通。 EmployeeIdentityIdConverter#fromRequestId 抛出空指针异常,因为字符串参数为空。因此,当 id 为 null 时,我添加了空检查和 return 默认 EmployeeIdentity。正如这个答案所描述的
修改后的EmployeeIdentityIdConverter#fromRequestId
@Override
public Serializable fromRequestId(String id, Class<?> aClass) {
if (id == null) {
return new EmployeeIdentity();
}
String[] parts = id.split("_");
return new EmployeeIdentity(parts[0], parts[1]);
}
但这引发了另一个问题。由于使用了默认构造函数并且 employeeId 和 companyId 为空,我现在通过空指针异常实现了 hashCode 和 equals。
为了解决这个问题,我为 employeeId 和 companyId 提供了默认值
**修改后的Employee#Employee()构造函数*
public Employee() {
this.employeeId = "";
this.companyId = "";
}
注意
我什至不确定我在上面做了什么。我只是在尝试解决出现的小问题。
顺便说一下,如果您猜到这行不通,那么您是对的。虽然我没有收到错误并且请求成功,但我没有得到预期的行为。使用空的 employeeId 和 companyId 创建了一个新条目。
如何将 POST 转换为 REST API 模型使用 @EmbeddedId 和 spring 启动数据休息?
我遇到了类似的问题,但找不到通过 POST /entities
端点创建新实体的解决方案。
但是,您也可以通过 PUT /entities/{newId}
端点创建新实体。并且转换器适用于这些端点。
我还完全拒绝了 POST 端点,避免了 500 个响应:
@PostMapping(value = "/themeMessages")
public ResponseEntity<Void> postThemeMessage() {
return new ResponseEntity<>(HttpStatus.METHOD_NOT_ALLOWED);
}
这是另一个解决方案。 (虽然仍然不完美。)
公开您的员工的 ID class:
@Configuration
protected class MyRepositoryRestConfigurer implements RepositoryRestConfigurer {
@Override
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
config.exposeIdsFor(ThemeMessage.class);
}
}
将以下行添加到您的转换器(在 POST 请求期间,id 将为空):
@Override
public Serializable fromRequestId(String id, Class<?> aClass) {
if(id==null) {
return null;
}
String[] parts = id.split("_");
return new EmployeeIdentity(parts[0], parts[1]);
}
下面的 POST
请求将起作用:
{
"id": {
"employeeId": "E-267",
"companyId": "D-432"
},
"name": "Spider Man",
"email": "spman@somedomain.com",
"phoneNumber": "+91-476253455"
}
但是,id 字段将在所有响应中公开。但也许这不是一个真正的问题,因为当你使用复合id时,通常意味着id不仅是一个抽象标识符,而且它的各个部分都有有意义的内容,应该出现在实体主体中。
实际上,我也在考虑将这些行添加到我自己的代码中....:)
我使用 Spring 引导数据 REST 构建了一个 REST API。我正在使用 embeddedId 并且还实现了 BackendIdConverter。
下面是我的 Embeddable class
@Embeddable
public class EmployeeIdentity implements Serializable {
@NotNull
@Size(max = 20)
private String employeeId;
@NotNull
@Size(max = 20)
private String companyId;
public EmployeeIdentity() {}
public EmployeeIdentity(String employeeId, String companyId) {
this.employeeId = employeeId;
this.companyId = companyId;
}
public String getEmployeeId() {
return employeeId;
}
public void setEmployeeId(String employeeId) {
this.employeeId = employeeId;
}
public String getCompanyId() {
return companyId;
}
public void setCompanyId(String companyId) {
this.companyId = companyId;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
EmployeeIdentity that = (EmployeeIdentity) o;
if (!employeeId.equals(that.employeeId)) return false;
return companyId.equals(that.companyId);
}
@Override
public int hashCode() {
int result = employeeId.hashCode();
result = 31 * result + companyId.hashCode();
return result;
}
}
这是我的员工模型
@Entity
@Table(name = "employees")
public class Employee {
@EmbeddedId
private EmployeeIdentity id;
@NotNull
@Size(max = 60)
private String name;
@NaturalId
@NotNull
@Email
@Size(max = 60)
private String email;
@Size(max = 15)
@Column(name = "phone_number", unique = true)
private String phoneNumber;
public Employee() {}
public Employee(EmployeeIdentity id, String name, String email, String phoneNumber) {
this.id = id;
this.name = name;
this.email = email;
this.phoneNumber = phoneNumber;
}
public EmployeeIdentity getId() {
return id;
}
public void setId(EmployeeIdentity id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
}
并使用我的嵌入 ID 而不是合格的 class 名称正确生成资源链接
@Component
public class EmployeeIdentityIdConverter implements BackendIdConverter {
@Override
public Serializable fromRequestId(String id, Class<?> aClass) {
String[] parts = id.split("_");
return new EmployeeIdentity(parts[0], parts[1]);
}
@Override
public String toRequestId(Serializable source, Class<?> aClass) {
EmployeeIdentity id = (EmployeeIdentity) source;
return String.format("%s_%s", id.getEmployeeId(), id.getCompanyId());
}
@Override
public boolean supports(Class<?> type) {
return Employee.class.equals(type);
}
}
这是我的存储库代码
@RepositoryRestResource(collectionResourceRel = "employees", path = "employees")
public interface EmployeeRepository extends PagingAndSortingRepository<Employee, EmployeeIdentity> {
}
这适用于 GET 请求,但我需要能够 POST。我注意到的第一件事是当我用 json
做 POST{
"id": {
"employeeId": "E-267",
"companyId": "D-432"
},
"name": "Spider Man",
"email": "spman@somedomain.com",
"phoneNumber": "+91-476253455"
}
这行不通。 EmployeeIdentityIdConverter#fromRequestId 抛出空指针异常,因为字符串参数为空。因此,当 id 为 null 时,我添加了空检查和 return 默认 EmployeeIdentity。正如这个答案所描述的
修改后的EmployeeIdentityIdConverter#fromRequestId
@Override
public Serializable fromRequestId(String id, Class<?> aClass) {
if (id == null) {
return new EmployeeIdentity();
}
String[] parts = id.split("_");
return new EmployeeIdentity(parts[0], parts[1]);
}
但这引发了另一个问题。由于使用了默认构造函数并且 employeeId 和 companyId 为空,我现在通过空指针异常实现了 hashCode 和 equals。
为了解决这个问题,我为 employeeId 和 companyId 提供了默认值
**修改后的Employee#Employee()构造函数*
public Employee() {
this.employeeId = "";
this.companyId = "";
}
注意
我什至不确定我在上面做了什么。我只是在尝试解决出现的小问题。
顺便说一下,如果您猜到这行不通,那么您是对的。虽然我没有收到错误并且请求成功,但我没有得到预期的行为。使用空的 employeeId 和 companyId 创建了一个新条目。
如何将 POST 转换为 REST API 模型使用 @EmbeddedId 和 spring 启动数据休息?
我遇到了类似的问题,但找不到通过 POST /entities
端点创建新实体的解决方案。
但是,您也可以通过 PUT /entities/{newId}
端点创建新实体。并且转换器适用于这些端点。
我还完全拒绝了 POST 端点,避免了 500 个响应:
@PostMapping(value = "/themeMessages")
public ResponseEntity<Void> postThemeMessage() {
return new ResponseEntity<>(HttpStatus.METHOD_NOT_ALLOWED);
}
这是另一个解决方案。 (虽然仍然不完美。)
公开您的员工的 ID class:
@Configuration
protected class MyRepositoryRestConfigurer implements RepositoryRestConfigurer {
@Override
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
config.exposeIdsFor(ThemeMessage.class);
}
}
将以下行添加到您的转换器(在 POST 请求期间,id 将为空):
@Override
public Serializable fromRequestId(String id, Class<?> aClass) {
if(id==null) {
return null;
}
String[] parts = id.split("_");
return new EmployeeIdentity(parts[0], parts[1]);
}
下面的 POST
请求将起作用:
{
"id": {
"employeeId": "E-267",
"companyId": "D-432"
},
"name": "Spider Man",
"email": "spman@somedomain.com",
"phoneNumber": "+91-476253455"
}
但是,id 字段将在所有响应中公开。但也许这不是一个真正的问题,因为当你使用复合id时,通常意味着id不仅是一个抽象标识符,而且它的各个部分都有有意义的内容,应该出现在实体主体中。
实际上,我也在考虑将这些行添加到我自己的代码中....:)