简体   繁体   English

Hibernate:使用额外列连接表,从一侧删除子项

[英]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. 更新公司时会出现问题。

  • When I add a new activity, all previous existing activities are persisted again. 当我添加新活动时,所有先前的现有活动将再次保留。
  • When I remove an activity, it is not removed from the table. 当我删除活动时,它不会从表中删除。

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 ? 能否帮助我同步Companyactivities集合而不从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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM