使用 Spring 数据 REST 保存嵌套对象
Save nested objects with Spring Data REST
我正在使用 Spring Boot,Spring Data REST,Hibernate,Spring JPA。
我有一个这样的模型:
@TypeDefs({ @TypeDef(name = "json", typeClass = JsonStringType.class),
@TypeDef(name = "jsonb", typeClass = JsonBinaryType.class) })
@EntityListeners({ AuditingEntityListener.class })
@MappedSuperclass
@Audited
public abstract class AbstractEntity extends AbstractPersistable<Long> {
private static final long serialVersionUID = 1L;
/* "UUID" and "UID" are Oracle reserved keywords -> "sid" */
@Column(name = "sid", unique = true, nullable = false, updatable = false, length = 36)
private String sid;
@CreatedBy
private String createdBy;
@CreatedDate
@Column(updatable = false)
private Instant createdDate;
@LastModifiedDate
private Instant lastModifiedDate;
@LastModifiedBy
private String lastModifiedBy;
// Trick to start version counting from 1 instead of 0
@Version
private long version = 1;
public AbstractEntity() {
}
@PrePersist
public void initializeUUID() {
if (sid == null) {
sid = UUID.randomUUID().toString();
}
}
@Override
@JsonIgnore
@ApiModelProperty(hidden = true)
public Long getId() {
return super.getId();
}
@Override
@JsonIgnore
@ApiModelProperty(hidden = true)
protected void setId(Long id) {
super.setId(id);
}
public String getSid() {
return sid;
}
public Instant getCreatedDate() {
return createdDate;
}
public Instant getLastModifiedDate() {
return lastModifiedDate;
}
public String getLastModifiedBy() {
return lastModifiedBy;
}
public long getVersion() {
return version;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
AbstractEntity other = (AbstractEntity) obj;
if (sid == null) {
if (other.sid != null)
return false;
} else if (!sid.equals(other.sid)) {
if (getId() == null) {
if (other.getId() != null)
return false;
} else {
if (!getId().equals(other.getId()))
return false;
}
}
return true;
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((sid == null) ? 0 : sid.hashCode());
return result;
}
}
@Entity
public class ParentEntity extends AbstractEntity {
private String name;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true, mappedBy = "parentEntity")
@OnDelete(action = OnDeleteAction.CASCADE)
private List<NestedEntity> rows = new ArrayList<>();
}
@Entity
public class NestedEntity extends AbstractEntity {
private String name;
@ManyToOne(fetch = FetchType.LAZY, optional = false)
private ParentEntity parentEntity;
}
我正在尝试使用 SDR 为我的 ParentEntity class 提供的默认 POST 方法。
我的存储库是:
@Transactional
@PreAuthorize("isAuthenticated()")
public interface ParentEntityRepository extends PagingAndSortingRepository<ParentEntity, Long> {
}
我想从客户端创建一个 POST(Angular,但我首先尝试使用 Swagger)发送 ParentEntity 和嵌套对象 NestedEntity 因为我希望保存发生在同一个交易。
所以我发送这个 Json:
{
"name": "Test",
"_embedded": {
"rows": [
{
"name": "Nested object"
}
]
}
}
不幸的是,只有父实体保存在数据库中。我尝试 - 只是为了测试 - 覆盖 ParentEntityRepository
中的方法 save() 以便调试并查看收到的内容。我看到 rows
列表是空的。
我的代码有什么问题?您有什么建议可以帮助我了解我的数据在哪里丢失了吗?
只需关闭 NestedEntityRepository
的导出(或将其删除):
@RepositoryRestResource(exported = false)
public interface NestedEntityRepository extends JpaRepository<NestedEntity, UUID> {
}
并提供两个实体之间双向关联的同步。例如像这样:
public class ParentEntity {
// ...
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true, mappedBy = "parentEntity")
private List<NestedEntity> rows;
public void setRows(List<NestedEntity> rows) {
if (this.rows != null) {
this.rows.forEach(row -> row.setParentEntity(null));
}
if (rows != null) {
rows.forEach(row -> row.setParentEntity(this));
}
this.rows = rows;
}
}
或者把你的关联变成单向的。
我正在使用 Spring Boot,Spring Data REST,Hibernate,Spring JPA。 我有一个这样的模型:
@TypeDefs({ @TypeDef(name = "json", typeClass = JsonStringType.class),
@TypeDef(name = "jsonb", typeClass = JsonBinaryType.class) })
@EntityListeners({ AuditingEntityListener.class })
@MappedSuperclass
@Audited
public abstract class AbstractEntity extends AbstractPersistable<Long> {
private static final long serialVersionUID = 1L;
/* "UUID" and "UID" are Oracle reserved keywords -> "sid" */
@Column(name = "sid", unique = true, nullable = false, updatable = false, length = 36)
private String sid;
@CreatedBy
private String createdBy;
@CreatedDate
@Column(updatable = false)
private Instant createdDate;
@LastModifiedDate
private Instant lastModifiedDate;
@LastModifiedBy
private String lastModifiedBy;
// Trick to start version counting from 1 instead of 0
@Version
private long version = 1;
public AbstractEntity() {
}
@PrePersist
public void initializeUUID() {
if (sid == null) {
sid = UUID.randomUUID().toString();
}
}
@Override
@JsonIgnore
@ApiModelProperty(hidden = true)
public Long getId() {
return super.getId();
}
@Override
@JsonIgnore
@ApiModelProperty(hidden = true)
protected void setId(Long id) {
super.setId(id);
}
public String getSid() {
return sid;
}
public Instant getCreatedDate() {
return createdDate;
}
public Instant getLastModifiedDate() {
return lastModifiedDate;
}
public String getLastModifiedBy() {
return lastModifiedBy;
}
public long getVersion() {
return version;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
AbstractEntity other = (AbstractEntity) obj;
if (sid == null) {
if (other.sid != null)
return false;
} else if (!sid.equals(other.sid)) {
if (getId() == null) {
if (other.getId() != null)
return false;
} else {
if (!getId().equals(other.getId()))
return false;
}
}
return true;
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((sid == null) ? 0 : sid.hashCode());
return result;
}
}
@Entity
public class ParentEntity extends AbstractEntity {
private String name;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true, mappedBy = "parentEntity")
@OnDelete(action = OnDeleteAction.CASCADE)
private List<NestedEntity> rows = new ArrayList<>();
}
@Entity
public class NestedEntity extends AbstractEntity {
private String name;
@ManyToOne(fetch = FetchType.LAZY, optional = false)
private ParentEntity parentEntity;
}
我正在尝试使用 SDR 为我的 ParentEntity class 提供的默认 POST 方法。 我的存储库是:
@Transactional
@PreAuthorize("isAuthenticated()")
public interface ParentEntityRepository extends PagingAndSortingRepository<ParentEntity, Long> {
}
我想从客户端创建一个 POST(Angular,但我首先尝试使用 Swagger)发送 ParentEntity 和嵌套对象 NestedEntity 因为我希望保存发生在同一个交易。
所以我发送这个 Json:
{
"name": "Test",
"_embedded": {
"rows": [
{
"name": "Nested object"
}
]
}
}
不幸的是,只有父实体保存在数据库中。我尝试 - 只是为了测试 - 覆盖 ParentEntityRepository
中的方法 save() 以便调试并查看收到的内容。我看到 rows
列表是空的。
我的代码有什么问题?您有什么建议可以帮助我了解我的数据在哪里丢失了吗?
只需关闭 NestedEntityRepository
的导出(或将其删除):
@RepositoryRestResource(exported = false)
public interface NestedEntityRepository extends JpaRepository<NestedEntity, UUID> {
}
并提供两个实体之间双向关联的同步。例如像这样:
public class ParentEntity {
// ...
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true, mappedBy = "parentEntity")
private List<NestedEntity> rows;
public void setRows(List<NestedEntity> rows) {
if (this.rows != null) {
this.rows.forEach(row -> row.setParentEntity(null));
}
if (rows != null) {
rows.forEach(row -> row.setParentEntity(this));
}
this.rows = rows;
}
}
或者把你的关联变成单向的。