gpt4 book ai didi

spring-boot - 如何在 JPA 中对多级子级执行所有级联操作(PERSIST、UPDATE、REMOVE)

转载 作者:行者123 更新时间:2023-12-04 20:28:26 24 4
gpt4 key购买 nike

我有 3 个表(表 1、表 2、表 3)。表 1 与表 2 相关,@onetomany 使用主键。表 2 与@manytoone 的表 3 相关。表 2 有 EmbeddedId。

当我使用表 1 的主键获取详细信息时,我能够获取表 2 和表 3 中的数据。但我无法进行保存和删除。保存和删除发生在表 1 的子表(即表 2)上,但不影响表 3(表 2 的子表)

下面是所有三个表的实体模型

 @Entity
@Table(name = "FEATUREMASTER")
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})

public class FeatureMaster implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;

@Id
@Column(name = "FGID")
private String featureid;

@Column(name = "FEATURENAME", nullable = false, unique = false)
private String featurename;

@Column(name = "DESCRIPTION", nullable = true, unique = false)
private String description;

@Column(name = "LIBNAME", nullable = true, unique = false)
private String libname;

@Column(name = "ISENABLED", nullable = false, unique = false)
private String isenabled;

@Column(name = "EDRULEGRP", nullable = true, unique = false)
private String edrulegrp;

// Do Not use - [orphanRemoval = true & CascadeType.ALL]- If used, deletion is not happening
@OneToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@JoinColumn(name = "FGID")
private List<CfgMaster> parameters;

// Getters and Setters
}


@Entity
@Table(name = "CFGMASTER")
public class CfgMaster implements Serializable {

/**
*
*/
private static final long serialVersionUID = 1L;

@EmbeddedId
private CfgMasterPK id;

@Column(name = "CONFIGNAME", length = 45, nullable = true, unique = false)
private String parameter_name;

@Column(name = "CONFIGTYPE", length = 20, nullable = true, unique = false)
private String type;

@Column(name = "SUBPARAM", nullable = true, unique = false)
private Integer subparam;

@Column(name = "CONFIGDESCRIPTION", nullable = true, unique = false)
private String description;

@Column(name = "CONFIGLIMITFROM", nullable = true, unique = false)
private String from;

@Column(name = "CONFIGLIMITTO", nullable = true, unique = false)
private String to;

@ManyToOne(cascade = {CascadeType.ALL}, optional = true, fetch = FetchType.LAZY )
// @ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, fetch = FetchType.LAZY)
@NotFound(action=NotFoundAction.IGNORE) // This is required to handle when no CfgData is found
@JoinColumns({
@JoinColumn(name = "FGID", insertable = false, updatable = false),
@JoinColumn(name = "DATAKEY", insertable = false, updatable = false)
})
private CfgData cfgData;

//Getters and Setters
}

@Entity
@Table(name = "CFGDATA")
public class CfgData implements Serializable {

/**
*
*/
private static final long serialVersionUID = 1L;


/*@EmbeddedId
private CfgDataPK id;*/

@Id
@Column(name = "FGID")
private String fgid;

@Id
@Column(name = "DATAKEY")
private String datakey;

@Column(name = "EPID", nullable = false, unique = false)
private int epid;


@Column(name = "RESERVED1", length = 45, nullable = true, unique = false)
private String reserved1;

@Column(name = "VALUE1", length = 100, nullable = true, unique = false)
private String value1;

@Column(name = "VALUE2", length = 100, nullable = true, unique = false)
private String value2;
//Getters and Setters
}

我面临的问题是,我无法通过传递 FeatureMaster 的主 ID 来删除/保存 CfgData 的实体。我所做的任何操作都只影响父和子,而不影响孙子 (CfgData)
我尝试了很多谷歌搜索,但找不到解决方案。

最佳答案

(这里假设 CfgMaster 的 PK 是 FGID - 希望这是正确的。如果是这样......我想我可以解释发生了什么,尽管用当前的表映射解决它很棘手)

看起来问题与 insertable = false, updatable = false 的存在与否有关在外键上。

如果同一实体上有两个属性映射到同一列,则使用这些的通常原因。 Hibernate 需要知道从哪个属性设置列值,因此最多可以写一个属性。

看起来这是这里的问题,但两次:

先上 FeatureMaster , parameters集合使用 FGID 的外键连接列.因为这是一个 @OneToMany这实际上是 CFGMASTER 上的一个专栏,它(假定)已经被 id 映射属性,第二个映射需要是只读的。

通过此更改,来自 FeatureMaster 的级联删除至 CfgMaster开始工作:

@OneToMany(cascade = { CascadeType.ALL }, orphanRemoval = true)
@JoinColumn(name = "FGID", insertable = false, updatable = false)
private List<CfgMaster> parameters = new ArrayList<>();

其次在 CfgMaster , cfgData属性使用只读 @JoinColumns .我认为这样做的原因是(假设) FGID 上的重叠柱子?

不幸的是,因为这些是 CFGMASTER 上的外键列。 ,这有效地使 CfgMaster.cfgData属性也是只读的。例如。切换到非重叠的可写列也启用了级联删除:
@ManyToOne(cascade = {
CascadeType.ALL }, optional = true, fetch = FetchType.LAZY)
// @ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, fetch = FetchType.LAZY)
@NotFound(action = NotFoundAction.IGNORE) // This is required to handle when no CfgData is found
@JoinColumns({
@JoinColumn(name = "FGID2"),
@JoinColumn(name = "DATAKEY") })
private CfgData cfgData;

这甚至适用于孙子级联删除。

然而,这显然引出了下一个问题——有没有办法获得 CfgData 的 PK?也成为两部分外键的一部分?我见过外键是主键的例子,但以前没有额外的列。很明显,您已经在这里进行了管理,但副作用是该关系也是只读的,至少对于级联而言是这样。

尽管这不是您希望听到的,但从 Hibernate 的角度来看,这确实是有道理的。例如。如果@ManyToOne 属性为空,Hibernate 会希望将两列都为空,这对于主键来说是一个问题。除非其他人知道得更好,否则我认为选择是更改数据库映射,或者如果这不是一个选项,您将需要编写 CfgData 的级联删除代码。的。

关于spring-boot - 如何在 JPA 中对多级子级执行所有级联操作(PERSIST、UPDATE、REMOVE),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52441668/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com