java.lang.IllegalStateException:同一实体的多个表示形式与@ManyToMany 3个实体
我有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
@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;
}
我做了以下工作:
Functionality1, Functionality2, Functionality3
Permission1 with Functionality1, Functionality2
Permission2 with Functionality2, Functionality3
Role1 with Permission1 and Permission2
通过删除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<>();