I have a 'tag' mechanism (kind of like Gmail's labels) with which I want to tag another entity, for the sake of the question - employees.
我有一个'标记'机制(有点像Gmail的标签),我想用它来标记另一个实体 - 为了问题 - 员工。
The Tag entity is simple and contains only name and looks as follows:
Tag实体很简单,只包含名称,如下所示:
@Entity
public class Tag implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "tag_id", unique = true, nullable = false)
private Long id;
@Column(name = "name", unique = true)
private String name;
@ManyToMany(fetch = FetchType.LAZY, mappedBy = "tags")
private Set<Employee> employees = new HashSet<>(0);
public String getName() {
return name;
}
public void setName(final String name) {
this.name = name;
}
public Set<Employee> getEmployees() {
return employees;
}
}
My Employee entity looks like this:
我的员工实体如下所示:
@Entity
public class Employee implements Serializable {
private static final long serialVersionUID = -6809049173391335091L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "employee_id", unique = true, nullable = false)
private Long id;
@Column
private String name;
@Column
private String description;
@Column
@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.MERGE)
@JoinTable(name = "employee_tag", joinColumns = {
@JoinColumn(name = "employee_id", nullable = false, updatable = false) },
inverseJoinColumns = { @JoinColumn(name = "tag_id",
nullable = false, updatable = false) })
private List<Tag> tags = new ArrayList<>();
// Rest of Getters and Setters
public List<Tag> getTags() {
return tags;
}
public void setTagsFromString(final String tags) {
String[] realTagsSplitted = tags.split(",");
for(String tagString: realTagsSplitted) {
Tag tag = new Tag();
tag.setName(tagString);
this.tags.add(tag);
}
}
What I would like to do is to be able to add from the UI tags to an Employee entity. But the tags are plain strings in the UI. I would like that when the Employee entity is persisted to have the tags persisted as well BUT I don't want duplications in the tags table (by duplication I, of course, mean that no two tags should exist with the same name but different ids).
我想要做的是能够从UI标签添加到Employee实体。但标签是UI中的纯字符串。我希望当持久化Employee实体使标签保持不变时我也不希望在标签表中重复(通过复制我当然意味着不应该存在两个具有相同名称但不同ID的标签)。
Meaning - if the tag "Tag1" exists in the table and the tag "Tag2" doesn't and in the UI the user adds both "Tag1" and "Tag2" to Employee "Employee1" I would like to:
含义 - 如果表中存在标记“Tag1”而标记“Tag2”不存在,并且在UI中用户将“Tag1”和“Tag2”添加到Employee“Employee1”,我想:
- Create a new row in the join-table that binds the id of "Employee1" to the id of "Tag1".
- Create a new row in the Tag table with "Tag2"
- Create a new row in the join-table that binds the id of "Employee1" to the id of the newly created "Tag2".
在join-table中创建一个新行,该行将“Employee1”的id绑定到id“Tag1”。
使用“Tag2”在Tag表中创建一个新行
在join-table中创建一个新行,该行将“Employee1”的id绑定到新创建的“Tag2”的id。
I really prefer to handle it on the code level, preferably with annotations if a solution exists. I'm trying to avoid DB triggers and things that are not obvious from reading the code.
我真的更喜欢在代码级别处理它,如果存在解决方案,最好使用注释。我试图避免数据库触发器和通过阅读代码不明显的事情。
1 个解决方案
#1
You should handle this on the service level, not in entities. Something along these steps:
您应该在服务级别而不是实体中处理此问题。这些步骤:
- Create a method like
findOrCreateTag(tagName)
, which would return existing tag from the database if it exists, or create a new one if it doesn't exist - Call this method for each tag you get from UI, and add it to
employee#tags
(also, add the employee totag#employees
) - Save changes to employee
创建一个像findOrCreateTag(tagName)这样的方法,它会从数据库中返回现有标记(如果存在),或者如果它不存在则创建一个新标记
从UI获取的每个标记调用此方法,并将其添加到employee#tags(同样,将该员工添加到标记#employees)
保存对员工的更改
One small thing, remove @Column
from Employee#tags
mapping.
一件小事,从Employee#tags映射中删除@Column。
#1
You should handle this on the service level, not in entities. Something along these steps:
您应该在服务级别而不是实体中处理此问题。这些步骤:
- Create a method like
findOrCreateTag(tagName)
, which would return existing tag from the database if it exists, or create a new one if it doesn't exist - Call this method for each tag you get from UI, and add it to
employee#tags
(also, add the employee totag#employees
) - Save changes to employee
创建一个像findOrCreateTag(tagName)这样的方法,它会从数据库中返回现有标记(如果存在),或者如果它不存在则创建一个新标记
从UI获取的每个标记调用此方法,并将其添加到employee#tags(同样,将该员工添加到标记#employees)
保存对员工的更改
One small thing, remove @Column
from Employee#tags
mapping.
一件小事,从Employee#tags映射中删除@Column。