Java 休眠多对多级联类型问题

Java 休眠多对多级联类型问题,java,hibernate,jpa,Java,Hibernate,Jpa,我目前正在一个项目中使用Hibernate,在建立多对多关系时遇到了问题。我认为我的问题与级联类型有关 场景是我们有一个广告,每个广告可以有很多标签,但每个标签可以与许多广告相关。广告实体的多个注释为: @ManyToMany(fetch = FetchType.LAZY, cascade = { CascadeType.MERGE, CascadeType.DETACH, CascadeType.REFRESH }) @JoinTable(name = "adMediaAdvertiserTa

我目前正在一个项目中使用Hibernate,在建立多对多关系时遇到了问题。我认为我的问题与级联类型有关

场景是我们有一个广告,每个广告可以有很多标签,但每个标签可以与许多广告相关。广告实体的多个注释为:

@ManyToMany(fetch = FetchType.LAZY, cascade = { CascadeType.MERGE, CascadeType.DETACH, CascadeType.REFRESH })
@JoinTable(name = "adMediaAdvertiserTag",
        joinColumns = { @JoinColumn(name = "adMediaId") },
        inverseJoinColumns = { @JoinColumn(name = "advertiserTagId") })
@ManyToMany(mappedBy = "advertiserTags", fetch = FetchType.LAZY, cascade = { CascadeType.PERSIST, CascadeType.MERGE })
标记实体上的多个映射是:

@ManyToMany(fetch = FetchType.LAZY, cascade = { CascadeType.MERGE, CascadeType.DETACH, CascadeType.REFRESH })
@JoinTable(name = "adMediaAdvertiserTag",
        joinColumns = { @JoinColumn(name = "adMediaId") },
        inverseJoinColumns = { @JoinColumn(name = "advertiserTagId") })
@ManyToMany(mappedBy = "advertiserTags", fetch = FetchType.LAZY, cascade = { CascadeType.PERSIST, CascadeType.MERGE })
我看到两种不同的错误,这取决于级联类型的配置以及数据库中是否已经存在标记

如果广告上的级联类型不包括PERSIST,并且标记不存在,则我们会得到以下异常:

TransientObjectException: object references an unsaved transient instance
如果广告上的层叠类型确实包含PERSIST,并且标记已经存在,我们得到:

PersistentObjectException: detached entity passed to persist
我能让它工作的唯一方法不是将PERSIST作为级联类型,而是循环遍历每个标记并将它们保存到会话中

这是正确的方法吗?有没有办法让hibernate自动为我处理这个问题

如果这不清楚或者您需要更多信息,请告诉我

更新

我正在使用一个服务保存这些对象,该服务使用springframework的save方法crudepository对象。有很多代码,所以我不能完全发布


我目前没有为任何试图保存的对象调用任何合并或持久化方法。我觉得Hibernate会帮我处理这类事情。

你能添加你用来保存广告和标签对象的代码吗。我使用以下代码进行了测试(我相信与您的代码类似),它可以正常工作:

User user = new User();
Role role = new Role();
role.setId("TEST_ROLE");
user.getRoles().add(role);

entityManager.persist(user);

User user2 = new User();
user2.getRoles().add(role);
entityManager.persist(user2);
System.out.println(user2.getId());
在用户界面中,我有:

@ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.PERSIST)
@JoinTable(name = "user_roles",
        joinColumns = {@JoinColumn(name = "user_id", nullable = false, updatable = true)},
        inverseJoinColumns = {@JoinColumn(name = "role_id", nullable = false, updatable = true)})
protected List<Role> roles = new ArrayList<>();
@ManyToMany(fetch=FetchType.EAGER,cascade=CascadeType.PERSIST)
@JoinTable(name=“用户角色”,
joinColumns={@JoinColumn(name=“user_id”,nullable=false,updateable=true)},
inverseJoinColumns={@JoinColumn(name=“role\u id”,nullable=false,updateable=true)})
受保护的列表角色=新的ArrayList();
我的职责是:

@ManyToMany(mappedBy="roles")
protected List<User> users;
@ManyToMany(mappedBy=“角色”)
受保护的名单用户;

您是说有些标签可能已经存在,因为有些标签是新的,需要保留。如果是这样,它不应该是调用
merge
而不是
persist
方法吗?是的,这是正确的。我已经试过了,但是当添加一个新标记时,它返回TransientObject异常:对象引用一个未保存的瞬态实例。你是说CascadeType还是用来保存对象的方法?我是指方法。不,我不调用它们。你看到这个问题的更新了吗?我使用的是spring框架的crudepository。我假设save方法可以处理合并和在引擎盖下持久化。你知道这是不是真的吗?谢谢你的回答,但这是我刚才解释的一个场景,当我们有一个现有的标签(或者你的案例中的角色)时,它不适用于这个场景。我将用更多的上下文更新这个问题。我刚刚注意到对persist方法的调用,每个新创建的对象都需要这个方法吗?是的,在这种情况下,您需要使它持久化一个新用户,并且角色对象将被持久化,间接地因为级联。您看到我的更新了吗?我假设当我们调用save时,spring框架的crudepository会为我们处理这个问题?我没有使用crudepository,所以不确定它是否与您的错误有关。您能否尝试使用entityManager持久化您的对象,看看它是否有帮助。如果是这样,那么你就知道接下来要调查什么。要在spring注释类中获取entityManager,可以执行
@PersistenceContext-protectedEntityManager entityManager