休眠更新子集合
Hibernate update child collection
我有一个父项 class 'Task' 并且其中有一个子项 'Tag'。我希望标签名称(参见标签 class)是唯一的,但是当我试图保存父 class 时,正在创建一个新的子记录。我怎样才能消除重复的子记录。
这是我的代码
任务等级
@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)
请帮我解决这个问题。提前谢谢大家。
您应该执行以下操作之一:
- 要么放弃设置以级联关系上的所有内容,分别保留标签,然后将标签分配给任务。
- 使用 List 代替 Set。它不应该允许你添加相同的标签两次(在 Tag 上实现一个 equals 方法来检查名称)
让我看看我是否理解流程:
1.你创建一个任务
2. 您为任务指定了一些标签名称,但您没有 select 已经存在的标签列表中的名称,您只是写下名称
3. 创建 TagDTO 并将它们添加到 TaskDTO 的列表中
4.当你保存你想要的TaskDTO时,系统会自动判断如果标签名已经存在不重复,也不会报错。
在这种情况下,您必须单独处理TagDTO 保存。所以,你有你的标签列表,你检查数据库中是否有,如果没有,你保存它们并取回持久实体,如果是,你从数据库中获取记录,然后将它们添加到列表中TaskDTO 并为 TaskDTO 进行保存。您还需要禁用级联 (cascade = CascadeType.ALL),以免强制进行第二次保存(以及可能出现的唯一性错误)。
我终于解开了这个谜团
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;
}
我从数据库获取标签后开始了我的交易,然后我在我的数据库中看到了这个
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)
我有一个父项 class 'Task' 并且其中有一个子项 'Tag'。我希望标签名称(参见标签 class)是唯一的,但是当我试图保存父 class 时,正在创建一个新的子记录。我怎样才能消除重复的子记录。
这是我的代码
任务等级
@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)
请帮我解决这个问题。提前谢谢大家。
您应该执行以下操作之一: - 要么放弃设置以级联关系上的所有内容,分别保留标签,然后将标签分配给任务。 - 使用 List 代替 Set。它不应该允许你添加相同的标签两次(在 Tag 上实现一个 equals 方法来检查名称)
让我看看我是否理解流程: 1.你创建一个任务 2. 您为任务指定了一些标签名称,但您没有 select 已经存在的标签列表中的名称,您只是写下名称 3. 创建 TagDTO 并将它们添加到 TaskDTO 的列表中 4.当你保存你想要的TaskDTO时,系统会自动判断如果标签名已经存在不重复,也不会报错。
在这种情况下,您必须单独处理TagDTO 保存。所以,你有你的标签列表,你检查数据库中是否有,如果没有,你保存它们并取回持久实体,如果是,你从数据库中获取记录,然后将它们添加到列表中TaskDTO 并为 TaskDTO 进行保存。您还需要禁用级联 (cascade = CascadeType.ALL),以免强制进行第二次保存(以及可能出现的唯一性错误)。
我终于解开了这个谜团
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;
}
我从数据库获取标签后开始了我的交易,然后我在我的数据库中看到了这个
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)