休眠更新子集合

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)