Hibernate更新子集合

时间:2015-01-04 12:46:49

标签: java hibernate many-to-many

我有一个家长班'任务'它有孩子' 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)

请帮我解决这个问题。提前全部谢谢。

3 个答案:

答案 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)