The scenario is the following
I have 2 tables, Company and Activity. 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
I used this tutorial as a starting point
Below my code (getters and setters omitted)
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;
}
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)
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.
Can you please help me sync the activities
collection on Company
without removing elements from Activity
table ?
Thanks a lot!
I solved it. Here are the steps I followed.
First, I changed my Join table entity cascade types as follows
@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
@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). Instead you should be using the @JoinTable on your activities entity. 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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.