简体   繁体   中英

java.lang.IllegalStateException: Multiple representations of the same entity with @ManyToMany 3 entities

I have 3 entities with ManyToMany relationships:

Role Entity:

@Entity
public class Role {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer roleID;
    private String roleName;
    private String description;

    @ManyToMany(cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH}, fetch = FetchType.EAGER)
    @JoinTable(name = "role_permission", joinColumns = {@JoinColumn(name = "role_id")}, inverseJoinColumns = {@JoinColumn(name = "permission_id")})
    private Set<Permission> permissions = new LinkedHashSet<Permission>();
}

Permission Entity:

@Entity
public class Permission {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int permissionID;
    private String permissionName;
    private String description;

    @ManyToMany(cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH}, fetch = FetchType.EAGER)
    @JoinTable(name = "permission_functionality", joinColumns = {@JoinColumn(name = "permission_id")}, inverseJoinColumns = {@JoinColumn(name = "functionality_id")})
    private Set<Functionality> functionalities = new LinkedHashSet<>();
}

Functionality Entity:

@Entity
public class Functionality {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String name;
}

I did the following:

  1. I have created 3 functionalities:

     Functionality1, Functionality2, Functionality3
  2. Then created 2 permissions:

     Permission1 with Functionality1, Functionality2 Permission2 with Functionality2, Functionality3
  3. Then created a role:

     Role1 with Permission1 and Permission2

I am getting the following exception:

java.lang.IllegalStateException: Multiple representations of the same entity [com.persistence.entity.admin.Functionality#1] are being merged. Detached: [com.persistence.entity.admin.Functionality@4729256a]; Detached: [com.persistence.entity.admin.Functionality@56ed25db]

通过删除权限实体上的 CascadeType.MERGE 修复它

正确的解决方案是升级到 hibernate 4.2.15 / 4.3.6 或更高版本,并将以下几行添加到您的 persistence.xml 中:

<property name="hibernate.event.merge.entity_copy_observer" value="allow"/>

Check your equals and hashCode method, ensure that it is consistent and correctly defined. For example I had copied and mistakenly pasted another-class when computing hashCode, this caused the object never to be equal with itself :(.

就像其他人的答案基于HHH-9106 一样,但是,因为我使用的是带有基于 Java 的注释的 Spring Boot,所以我不得不在application.properties使用以下内容:

spring.jpa.properties.hibernate.event.merge.entity_copy_observer=allow

I ran into the same problem too and solved it by add a few configs in application.yaml files.

  jpa:
    properties:
      hibernate:
        enable_lazy_load_no_trans: true
        event:
          merge:
            entity_copy_observer: allow

See it here How to persist a new entity containing multiple identical instances of another unpersisted entity with spring-boot and JPA?

I could fix it by replacing

cascade = CascadeType.All

with

casecade={CascadeType.PERSIST,CascadeType.REMOVE}

For Hibernate see the workaround here HHH-9106 .

就我而言,在同一个 @Transactional 块中移动 fetch 操作和 save 操作解决了这个问题。

error occurs when we have multiple object of same time in HashSet.Possible due to incorrect hash function.Hashset check equality of object on the basis of hash function between two objects.

Way to debug

Just try to print hashset you will see multiple object of same type.

Solution::#

  • Use HashSet while defining one to many relationships.
  • Avoid using Lists.
  • Make sure your hash function should be correct.
**@LazyCollection(LazyCollectionOption.FALSE** 

@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)

@JoinColumn(name = "translate_id")

I fixed this issue by removing cascade = CascadeType.ALL in your case ( cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH} )

My code source:

Before

@ManyToMany(fetch=FetchType.EAGER, cascade = CascadeType.ALL)
@JoinTable(
    name = "link_module_parcour",
    joinColumns = {@JoinColumn(name = "module_id", referencedColumnName = "id")},
    inverseJoinColumns = {@JoinColumn(name = "parcour_id", referencedColumnName = "id")})
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
@BatchSize(size = 20)
private Set<Parcour> parcours = new HashSet<>();

After

@ManyToMany(fetch=FetchType.EAGER)
@JoinTable(
    name = "link_module_parcour",
    joinColumns = {@JoinColumn(name = "module_id", referencedColumnName = "id")},
    inverseJoinColumns = {@JoinColumn(name = "parcour_id", referencedColumnName = "id")})
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
@BatchSize(size = 20)
private Set<Parcour> parcours = new HashSet<>();

If you remove the cascade merge you won't be able to update the entity when updating the parent. The case will be right if you don't want to update the child, but if you want to update the child when updating the parent removing merge will only not show the error but the issue will still exist.

What happened with me: I got the same exception but I need Cascade.merge. After searching I found that some of the values I was using when creating the entity for the first time are updated and removed from the code but in the database, they still exist and when removing them from the database also work as expected.

To clarify the case: Let's say I have an enum('ACTIVE', 'NOT_ACTIVE', 'SUSPENDED') and the field using this enum is key, when updating the code and removing the NOT_ACTIVE we should alter the database table with the new values enum('ACTIVE', 'SUSPENDED')

I had similar issue and it is resolved when I replace CascadeType.All with {CascadeType.persist, CascadeType.remove} .

Let me know if it works.

Just a note to say I am using Hibernate Core 4.3.8 in a Spring MVC application, based on Spring Core 4.1.6. The workaround:

<property name="hibernate.event.merge.entity_copy_observer" value="allow"/>

Did not work for me. I needed to remove the CascadeType.MERGE in order to correctly populate an @ManyToMany. Not sure if newer versions of Hibernate have fixed this.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM