休眠:加入带有额外列的表,从一侧删除子项
Posted
技术标签:
【中文标题】休眠:加入带有额外列的表,从一侧删除子项【英文标题】:Hibernate: Join table with extra columns, remove children from one side 【发布时间】:2016-10-13 13:50:18 【问题描述】:场景如下
我有 2 个表,Company 和 Activity。一家公司可以有一项或多项活动。其中一项活动是“主要”活动,所有其他活动都成为次要活动。
为了处理这个问题,我为连接表创建了 2 个实体(Activity、Company)和第三个实体,即 CompanyActivity
我以this tutorial为起点
在我的代码下方(省略了 getter 和 setter)
Company.java
@Entity
@Table(name = "T_COMPANY")
public class Company
@Id
@Column(name = "COM_ID")
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "company")
private List<CompanyActivity> activities = new ArrayList<>();
Activity.java
@Entity
@Table(name = "T_ACTIVITY")
public class Activity
@Id
@Column(name = "ACT_ID")
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String code;
private String description;
private boolean availableOnline;
CompanyActivity.java
@Entity
@Table(name = "T_COMPANY_ACTIVITY")
public class CompanyActivity
@Id
@Column(name = "COM_ACT_ID")
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "COM_ID")
private Company company;
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "ACT_ID")
private Activity activity;
private boolean primary;
为公司添加活动没有问题。 children 集合包含新添加的活动,并且总是有一个按预期标记为 primary。
更新公司时会出现问题。
当我添加一个新活动时,所有以前的现有活动都会再次保留。 当我删除一个活动时,它并没有从表中删除。我正在使用此代码更新公司的活动
company.getActivities().clear();
company.getActivities().addAll(newActivities);
company = repository.save(company);
在这段代码中,newActivities
有应该考虑的新活动(这个集合没有以前的,我只是将它们全部替换)
我尝试将orphanRemoval=true
添加到公司上的@OneToMany(cascade = CascadeType.ALL, mappedBy = "company")
,但是当没有其他公司使用它时,这会删除活动类型,这是错误的,因为它们应该始终可用。
您能帮我在Company
上同步activities
集合而不从Activity
表中删除元素吗?
非常感谢!
【问题讨论】:
【参考方案1】:我解决了。以下是我遵循的步骤。
首先,我将我的 Join 表实体级联类型更改如下
@Entity
@Table(name = "T_COMPANY_ACTIVITY")
public class CompanyActivity
@Id
@Column(name = "COM_ACT_ID")
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@ManyToOne(cascade = CascadeType.PERSIST, CascadeType.MERGE)
@JoinColumn(name = "COM_ID")
private Company company;
@ManyToOne(cascade = CascadeType.PERSIST, CascadeType.MERGE)
@JoinColumn(name = "ACT_ID")
private Activity activity;
private boolean primary;
然后,我再次将“orphanRemoval”属性添加到公司映射中,并更改了我的 CascadeTypes,如下所示
@OneToMany(cascade = CascadeType.PERSIST, CascadeType.MERGE, mappedBy = "empresa", orphanRemoval = true)
private List<CompanyActivity> activities = new ArrayList<>();
通过这些更改,我的映射使用我用来替换关系的相同代码按预期工作。
company.getActivities().clear();
company.getActivities().addAll(newActivities);
company = repository.save(company);
谢谢:)
【讨论】:
【参考方案2】:您创建实体的方式不正确。您无需为连接表 (CompanyActivity/T_COMPANY_ACTIVITY) 创建实体。相反,您应该在活动实体上使用 @JoinTable。如下所示:
@OneToMany(cascade = CascadeType.ALL, mappedBy = "company")
@JoinTable(
name = "T_COMPANY_ACTIVITY",
joinColumns = @JoinColumn(name = "COM_ID"),
inverseJoinColumns = @JoinColumn(name = "ACT_ID")
)
private List<CompanyActivity> activities = new ArrayList<>();
有关连接表的一对多/多对一如何工作的更详细说明:http://www.codejava.net/frameworks/hibernate/hibernate-one-to-many-association-on-join-table-annotations-example
【讨论】:
我需要为关系添加一个布尔属性。如果您查看 CompanyActivity,我添加了一个布尔值“主要”,用于确定公司的主要活动。用你描述的方法,我做不到。以上是关于休眠:加入带有额外列的表,从一侧删除子项的主要内容,如果未能解决你的问题,请参考以下文章