[英]Hibernate: Join table with extra columns, remove children from one side
The scenario is the following 场景如下
I have 2 tables, Company and Activity. 我有2个表,公司和活动。 A company can have one or more activities.
公司可以有一个或多个活动。 One of these activities is a "primary" activity, and all others become secondary.
其中一项活动是“主要”活动,所有其他活动都是次要活动。
To handle this, I created 2 entities (Activity, Company) and a third entity for the join table, which is CompanyActivity 为了解决这个问题,我为连接表创建了2个实体(Activity,Company)和第三个实体,即CompanyActivity
I used this tutorial as a starting point 我以本教程为出发点
Below my code (getters and setters omitted) 在我的代码下面(省略了getter和setter)
Company.java 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 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 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;
}
Adding activities for a company works without a problem. 为公司添加活动没有问题。 The children collection contains the newly added activities, and there is always one marked as primary as expected.
子集合包含新添加的活动,并且始终有一个标记为主要的预期。
The problem happens when updating a company. 更新公司时会出现问题。
I'm using this code to update a company' activities 我正在使用此代码更新公司的活动
company.getActivities().clear();
company.getActivities().addAll(newActivities);
company = repository.save(company);
In this code, newActivities
have the new activities that should be considered (this collection does not have the previous ones, I just replace them all) 在此代码中,
newActivities
具有应该考虑的新活动(此集合没有以前的那些,我只是将它们全部替换)
I tried adding orphanRemoval=true
to the @OneToMany(cascade = CascadeType.ALL, mappedBy = "company")
on Company, but this deletes the activity type when no other company is using it, which is wrong as they should be available always. 我尝试将
orphanRemoval=true
添加到公司的@OneToMany(cascade = CascadeType.ALL, mappedBy = "company")
,但是当没有其他公司正在使用它时,这会删除活动类型,这是错误的,因为它们应始终可用。
Can you please help me sync the activities
collection on Company
without removing elements from Activity
table ? 能否帮助我同步
Company
的activities
集合而不从Activity
表中删除元素?
Thanks a lot! 非常感谢!
I solved it. 我解决了 Here are the steps I followed.
以下是我遵循的步骤。
First, I changed my Join table entity cascade types as follows 首先,我更改了我的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;
}
Then, I added again the "orphanRemoval" property to Company mapping, and changed my CascadeTypes too, as follows 然后,我再次将“orphanRemoval”属性添加到公司映射,并更改了我的CascadeTypes,如下所示
@OneToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, mappedBy = "empresa", orphanRemoval = true)
private List<CompanyActivity> activities = new ArrayList<>();
With these changes, my mapping works as expected with the same code I used to replace the relationships. 通过这些更改,我的映射按预期工作,使用与替换关系相同的代码。
company.getActivities().clear();
company.getActivities().addAll(newActivities);
company = repository.save(company);
Thanks :) 谢谢 :)
The way you created your entities is not correct. 您创建实体的方式不正确。 You don't need to create an entity for your join table (CompanyActivity/T_COMPANY_ACTIVITY).
您无需为连接表创建实体(CompanyActivity / T_COMPANY_ACTIVITY)。 Instead you should be using the @JoinTable on your activities entity.
相反,您应该在您的活动实体上使用@JoinTable 。 Something like below:
如下所示:
@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<>();
for more detailed explanation on how One-to-Many/Many-to-One with Join tables work here: http://www.codejava.net/frameworks/hibernate/hibernate-one-to-many-association-on-join-table-annotations-example 有关如何使用Join表的一对多/多对一的更详细说明: http : //www.codejava.net/frameworks/hibernate/hibernate-one-to-many-association-on-join -table-注解-示例
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.