我有一个家长班'任务'它有孩子' Tag'在里面。我希望标签名称(请参阅Tag类)是唯一的,但是当我尝试保存父类时,正在创建一个新的子记录。如何消除重复的子记录。
这是我的代码
任务类
@Entity
@Table(name="tasks")
public class TaskDTO {
...
...
@ManyToMany(cascade = CascadeType.ALL,fetch = FetchType.EAGER)
@JoinTable( name = "task_tags",joinColumns = { @JoinColumn(name = "taskId") }, inverseJoinColumns = { @JoinColumn(name = "tagId") })
private List<TagDTO> tags = new ArrayList<TagDTO>();
}
标记类
@Entity
@Table(name="tags")
public class TagDTO {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "tagId")
private int tagId;
@Column(name = "tagName")
private String tagName;
}
TaskDAOImpl
@Repository("taskDAOImpl")
public class TaskDAOImpl implements TaskDAO {
@Override
public Integer saveTask(TaskDTO taskDTO) {
Integer identifier = null;
try {
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
..........
..........
identifier = (Integer) session.save(taskDTO);
return identifier;
} catch (Exception ex) {
logger.error("unable to save task ", ex);
}
return null;
}
当我保存标签时,我会在我的数据库中找到它。
mysql> select * from tags;
+-------+---------+
| tagId | tagName |
+-------+---------+
| 1 | java |
| 2 | java |
+-------+---------+
2 rows in set (0.00 sec)
mysql> select * from task_tags;
+--------+-------+
| taskId | tagId |
+--------+-------+
| 69 | 1 |
| 70 | 2 |
+--------+-------+
2 rows in set (0.00 sec)
我想消除两次保存的tagName。
但我想要这样的事情
mysql> select * from tags;
+-------+---------+
| tagId | tagName |
+-------+---------+
| 1 | java |
+-------+---------+
2 rows in set (0.00 sec)
mysql> select * from task_tags;
+--------+-------+
| taskId | tagId |
+--------+-------+
| 69 | 1 |
| 70 | 1 |
+--------+-------+
2 rows in set (0.00 sec)
请帮我解决这个问题。提前全部谢谢。
答案 0 :(得分:0)
您应该执行以下操作之一: - 删除设置以级联关系中的所有内容,单独保留标记,然后添加将标记分配给任务。 - 使用而不是列表集。它不应该允许您添加相同的标记两次(在Tag上实现一个equals方法来检查名称)
答案 1 :(得分:0)
让我看看我是否理解这个流程: 1.你创建一个任务 2.为任务指定一些标记名称,但不要从刚写入名称的现有标记列表中选择名称 3.您创建TagDTO并将它们添加到TaskDTO中的列表中 4.当您自动保存TaskDTO时,系统会自动确定标签名称是否已经存在,不会复制它,也不会出错。
在这种情况下,您必须单独处理TagDTO保存。所以,你有你的标签列表,你检查是否有数据库,如果没有,你保存它们并返回持久化实体,如果是,你从DB获取记录,然后你将它们添加到列表TaskDTO并为TaskDTO执行保存。您还需要禁用级联(cascade = CascadeType.ALL),以便不强制进行第二次保存(以及可能的唯一性错误)。
答案 2 :(得分:0)
最后我像这样解开了这个谜团
public Integer saveTask(TaskDTO taskDTO) {
Integer identifier = null;
try {
....
....
Session session = sessionFactory.getCurrentSession();
for(int i=0 ; i < taskDTO.getTags().size(); i++) {
TagDTO tagDTO = taskDTO.getTags().get(i);
TagDTO data = (TagDTO) session.createCriteria(TagDTO.class).add(Restrictions.eq("tagName", tagDTO.getTagName())).uniqueResult();
if(null == data) {
taskDTO.getTags().set(i,tagDTO);
} else {
taskDTO.getTags().set(i,data);
}
}
session.beginTransaction(); // <-- this is key point, started transaction from here.
for(int i = 0 ; i < taskDTO.getUsers().size() ; i++) {
UserDTO userDTO = taskDTO.getUsers().get(i);
userDTO = (UserDTO) session.get(UserDTO.class,userDTO.getUserId());
userDTO.getTasks().add(taskDTO);
taskDTO.getUsers().set(i,userDTO);
}
....
....
identifier = (Integer) session.save(taskDTO);
return identifier;
} catch (Exception ex) {
logger.error("unable to save task ", ex);
}
return null;
}
我从db获取标签后开始了我的事务,然后我在我的数据库中看到了这个
mysql> select * from tags;
+-------+---------+
| tagId | tagName |
+-------+---------+
| 11 | java |
+-------+---------+
1 row in set (0.00 sec)
mysql> select * from task_tags;
+--------+-------+
| taskId | tagId |
+--------+-------+
| 11 | 11 |
| 12 | 11 |
+--------+-------+
2 rows in set (0.00 sec)