java.lang.IllegalStateException:同一实体的多个表示形式与@ManyToMany 3个实体

java.lang.IllegalStateException:同一实体的多个表示形式与@ManyToMany 3个实体,java,hibernate,jpa,jpa-2.0,ejb-3.0,Java,Hibernate,Jpa,Jpa 2.0,Ejb 3.0,我有3个实体,有很多关系: 角色实体: @Entity public class Role { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer roleID; private String roleName; private String description; @ManyToMany(cascade = {CascadeType.MERGE, Ca

我有3个实体,有很多关系:

角色实体:

@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>();
}
@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<>();
}
@Entity
public class Functionality {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String name;
}
我做了以下工作:

  • 我创建了3个功能:

    Functionality1, Functionality2, Functionality3
    
  • 然后创建了2个权限:

    Permission1 with Functionality1, Functionality2
    
    Permission2 with Functionality2, Functionality3
    
  • 然后创建了一个角色:

    Role1 with Permission1 and Permission2 
    
  • 我得到以下例外情况:

    java.lang.IllegalStateException:正在合并同一实体[com.persistence.entity.admin.Functionality#1]的多个表示形式。分离:[com.persistence.entity.admin。Functionality@4729256a]; 分离:[com.persistence.entity.admin。Functionality@56ed25db]


    通过删除Hibernate权限实体上的CascadeType.MERGE来修复此问题。请参见此处的解决方法。

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


    请注意,我正在基于Spring Core 4.1.6的Spring MVC应用程序中使用Hibernate Core 4.3.8。解决办法:

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

    不适合我。我需要删除CascadeType.MERGE以正确填充@ManyToMany。不确定Hibernate的较新版本是否已修复此问题。

    检查equals和hashCode方法,确保其一致且定义正确。例如,我在计算hashCode时复制并错误粘贴了另一个类,这导致对象永远不会与自身相等:(.

    在我的例子中,在同一@Transactional块中移动fetch操作和save操作解决了问题。

    当哈希集中有多个同一时间的对象时,会发生错误。可能是由于哈希函数不正确。哈希集根据两个对象之间的哈希函数检查对象的相等性

    调试方法 只要试着打印hashset,您就会看到多个相同类型的对象

    解决方案:#
    • 在定义一对多关系时使用HashSet
    • 避免使用列表
    • 确保您的哈希函数应该是正确的

    我也遇到了同样的问题,通过在
    application.yaml
    文件中添加一些配置解决了这个问题

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

    请看这里

    我可以通过更换

    cascade = CascadeType.All
    


    像其他人一样,他们的答案基于但是,因为我使用基于Java的注释的Spring Boot,所以我必须在
    application.properties
    中使用以下内容:

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

    我通过删除您案例中的
    cascade=CascadeType.ALL
    解决了这个问题(
    cascade={CascadeType.MERGE,CascadeType.PERSIST,CascadeType.REFRESH}

    我的代码来源:

    之前

    @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<>();
    
    @ManyToMany(fetch=FetchType.EAGER,cascade=CascadeType.ALL)
    @可接合(
    name=“link\u module\u parcour”,
    joinColumns={@JoinColumn(name=“module_id”,referencedColumnName=“id”)},
    inverseJoinColumns={@JoinColumn(name=“parcour\u id”,referencedColumnName=“id”)}
    @缓存(用法=缓存并发策略。非严格读写)
    @批量大小(大小=20)
    private Set parcours=new HashSet();
    
    之后

    @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<>();
    
    @ManyToMany(fetch=FetchType.EAGER)
    @可接合(
    name=“link\u module\u parcour”,
    joinColumns={@JoinColumn(name=“module_id”,referencedColumnName=“id”)},
    inverseJoinColumns={@JoinColumn(name=“parcour\u id”,referencedColumnName=“id”)}
    @缓存(用法=缓存并发策略。非严格读写)
    @批量大小(大小=20)
    private Set parcours=new HashSet();
    
    请引用链接最相关的部分,以防目标站点无法访问或永久脱机。请参阅。或者,如果我的网络阻止了一些CSS文件,则该站点完全无法读取。该链接是关于
    hibernate.event.merge.entity\u copy\u observer
    属性的,该属性在撰写本文时已存在由其他答案覆盖。此属性适用于整个持久性上下文,仅用于测试目的。如果将其设置为“允许”或“日志”,Hibernate将继续按顺序合并两个分离的实体。但是合并的顺序没有定义。因此,这可能会导致意外的数据损坏。正确的解决方案是修复实体关系。@VHS您能解释一下如果我删除
    级联类型会发生什么情况吗?合并
    ?我认为这是所有地方的答案,但我打赌这是一个具有副作用的突破性更改。@ElMac不带
    CascadeType.MERGE
    ,如果您保存的对象引用了另一个对象,则需要手动存储该另一个对象;另一方面,使用
    CascadeType.MERGE
    ,Hibernate会自动为您执行此操作。因此您是正确的,这可能会导致其他问题。请尝试使用Hibernate级联注释代替JPA注释。例如,@cascade(CascadeType.SAVE_UPDATE)将替换{CascadeType.PERSIST,CascadeType.MERGE}。检查本文:如果我想合并现有实体,这会产生什么影响?当我删除
    级联类型时会发生什么?合并
    ?是的,有同样的问题,当我们删除合并级联时会发生什么?我想我知道为什么。这意味着如果实体被合并,相关实体也会被合并,而在这种情况下不是这样,因为我们只想创建一个新角色,但不想创建/更新权限。如果我不使用Hibernate怎么办?回答得很好!谢谢!IntelliJ有一个生成
    等于
    hashCode
    的过程,你可以查看它。这很有帮助!我正在使用Lombok的数据注释生成我所有的附加方法,when更改为Getter Setter而不是@Data问题已经解决。谢谢。
    等于父实体或分离实体的
    hashCode
    ?适用于我…:D(Spring Boot 1.4.1.版本)
    @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<>();
    
    @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<>();