Hibernate Ι;是否可以禁止使用CascadeType或其他注释替换实体上的现有子实体?

Hibernate Ι;是否可以禁止使用CascadeType或其他注释替换实体上的现有子实体?,hibernate,spring-boot,cascade,Hibernate,Spring Boot,Cascade,嗨,我正在尝试制作一个API,它使用这样一个实体: @Entity @NoArgsConstructor @Getter @Setter class ParentEntity { @OneToOne(cascade= {CascadeType.ALL}, orphanRemoval = true) private ChildEntity child; } 假设我在http://localhost:8080/api/v1/parent-实体/1 我想做的是能够通过以下方式进行(更新

嗨,我正在尝试制作一个API,它使用这样一个实体:

@Entity 
@NoArgsConstructor @Getter @Setter
class ParentEntity {
   @OneToOne(cascade= {CascadeType.ALL}, orphanRemoval = true)
   private ChildEntity child;
}
假设我在
http://localhost:8080/api/v1/parent-实体/1

我想做的是能够通过以下方式进行(更新):

我希望能够动态创建新的子实体,因此需要允许这样做(我想我需要
CascadeType.PERSIST
):

需要允许通过父级更新子级(我想我需要
CascadeType.MERGE

我还需要能够删除一个项目并将其从数据库中删除(我想我需要
CascadeType.remove
,以及
orphandremove=true
):

我需要的帮助是不允许这样做:

PUT parent-entities/1
{ "child": { "id": 2, "name": "other existing child" }}
答案可能与
CascadeType.REFRESH
CascadeType.DETACH
CascadeType.MERGE

从我的测试中,我不知怎么的无法让它工作。实际上,我设法摧毁了许多现有的子实体,使它们的名称等于null。我最好的猜测是
CascadeType.PERSIST,CascadeType.REFRESH,CascadeType.MERGE,CascadeType.REMOVE

上述动机:前端应用程序正在发送特定子实体的数据,但id错误-这导致了错误实体的变异,该实体完全不相关,而且附加到错误的父实体。但我仍然需要CascadeType.MERGE


感谢您的帮助

是的,这可以通过注释来完成。解决方案最终将向特定列添加可更新字段

您可以通过删除CascadeType.MERGE来阻止更新,但这样您也将无法更新ChildEntity.name。。。如果要防止特定字段的可更新性,请尝试以下操作

@实体
@吸气剂
@塞特
@诺尔格构装师
公共类ParentEntity实现可序列化{
私有静态最终长serialVersionUID=-312677362335903987L;
@身份证
@生成值
@列(可更新=false)
私人长id;
**@JoinColumn(可更新=false)**
@OneTONE(级联=级联类型.ALL,孤立删除=真)
私人儿童实体儿童;
}
@实体
@吸气剂
@塞特
@诺尔格构装师
公共类ChildEntity实现可序列化{
私有静态最终长serialVersionUID=-29038577072685774L;
@身份证
@生成值
私人长id;
私有字符串名称;
@杰索尼奥雷
@OneTONE(mappedBy=“child”)
私人父母实体父母;
}
@PutMapping
私人响应更新(
@请求主体(最终父实体){
返回响应的数量(可选的数量)(此.repo.saveAndFlush(实体));
}
要演示,请在application.properties中启用show sql

spring.jpa.show-sql=true
创建初始实体

PUT /parent-entity
{
    "child": {
        "name": "alpha"
    }
}

Hibernate: insert into ChildEntity (name, id) values (?, ?)
Hibernate: insert into ParentEntity (child_id, id) values (?, ?)


PARENT_ID   CHILD_ID    CHILD   NAME
1           2           2       alpha

更新名称

PUT /parent-entity
{
    "id": 1,
    "child": {
        "id": 2,
        "name": "beta"
    }
}

Hibernate: update ChildEntity set name=? where id=?


PARENT_ID   CHILD_ID    CHILD   NAME
1           2           2       beta

尝试更新ID

PUT /parent-entity
{
    "id": 1,
    "child": {
        "id": 3,
        "name": "gamma"
    }
}

{
    "timestamp": "2020-01-23T11:08:02.056+0000",
    "status": 500,
    "error": "Internal Server Error",
    "message": "could not execute statement; SQL [n/a]; constraint [\"FKGD5S6Q2V5J8MX33JL99EYCY5R: PUBLIC.PARENTENTITY FOREIGN KEY(CHILD_ID) REFERENCES PUBLIC.CHILDENTITY(ID) (2)\"; SQL statement:\ndelete from ChildEntity where id=? [23503-200]]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement",
    "path": "/parent-entities"
}


PARENT_ID   CHILD_ID    CHILD   NAME
1           2           2       beta


类似地,如果您想防止非引用列被更新,只需使用@column(updateable=false)

就可以了,因此您需要一个字段
name
作为唯一字段吗?不需要@Andronicus,这是不需要的。那么您想要的是什么?你想禁止彼此交换实体吗?@Andronicus是的,我在我想做的事情后面加了一句激励性的话(如果有注释的话)awesome似乎正是我想要的解决方案类型,没有额外的代码-我会在本地查看确认,我会接受并给予奖励-谢谢:)
PUT /parent-entity
{
    "child": {
        "name": "alpha"
    }
}

Hibernate: insert into ChildEntity (name, id) values (?, ?)
Hibernate: insert into ParentEntity (child_id, id) values (?, ?)


PARENT_ID   CHILD_ID    CHILD   NAME
1           2           2       alpha

PUT /parent-entity
{
    "id": 1,
    "child": {
        "id": 2,
        "name": "beta"
    }
}

Hibernate: update ChildEntity set name=? where id=?


PARENT_ID   CHILD_ID    CHILD   NAME
1           2           2       beta

PUT /parent-entity
{
    "id": 1,
    "child": {
        "id": 3,
        "name": "gamma"
    }
}

{
    "timestamp": "2020-01-23T11:08:02.056+0000",
    "status": 500,
    "error": "Internal Server Error",
    "message": "could not execute statement; SQL [n/a]; constraint [\"FKGD5S6Q2V5J8MX33JL99EYCY5R: PUBLIC.PARENTENTITY FOREIGN KEY(CHILD_ID) REFERENCES PUBLIC.CHILDENTITY(ID) (2)\"; SQL statement:\ndelete from ChildEntity where id=? [23503-200]]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement",
    "path": "/parent-entities"
}


PARENT_ID   CHILD_ID    CHILD   NAME
1           2           2       beta