JPA管理的映射具有不同的实体错误

deb*_*ris 9 java spring jpa spring-mvc spring-boot

我有一个表单,这个表单需要更新我的记录,但显然没有更新,我收到以下错误消息.在4天内处理此异常,我决定提问.如果您需要额外的信息,我可以添加一些.

JSP例外;

MergeContext#attempt to create managed -> managed mapping with different entities: [main.model.Users#1]; [main.model.Users#1]; nested exception is java.lang.IllegalStateException: MergeContext#attempt to create managed -> managed mapping with different entities: [main.model.Users#1]; [main.model.Users#1]
Run Code Online (Sandbox Code Playgroud)

Java例外;

java.lang.IllegalStateException: MergeContext#attempt to create managed -> managed mapping with different entities: [main.model.Users#1]; [main.model.Users#1]
Run Code Online (Sandbox Code Playgroud)

控制器; 它从表单获取位置用户和域信息并将其保存到DB;

@PostMapping("/save-personel-info")
public String savePersonelInfo(@RequestParam int id, HttpServletRequest request, @ModelAttribute("Users") Users users, @ModelAttribute("Positions") Positions positions, @ModelAttribute("Domains") Domains domains, ModelMap model){
    usersService.save(users);
    request.setAttribute("mode", "MODE_USERS");
    return "redirect:/index";
}
Run Code Online (Sandbox Code Playgroud)

服务;

@Service
@Transactional
public class UsersService {

    public void save(Users users){
        usersRepository.save(users);
    }
}
Run Code Online (Sandbox Code Playgroud)

形成;

<form:form method="POST" action="/save-personel-info" modelAttribute="Users">
    <tr>
        <form:input id="1-1-0" type="hidden" class="form-control" path="id"/>
            <td><form:input id="1-1-0" type="text" class="form-control" path="username" /></td>
            <td><form:input id="1-1-0" type="text" class="form-control" path="mail" /></td>
        <td>
            <form:select path="Positions" class="form-control">
                <form:options items="${Pst}"  itemValue="id" itemLabel="position_name" />
            </form:select> 
        </td>                                   
        <td>
            <form:select path="Domains" class="form-control">
                <form:options items="${Domains}"  itemValue="id" itemLabel="domain_name" />
            </form:select> 
        </td>
    </tr>
    <input type="submit" value="Submit" />
</form:form>
Run Code Online (Sandbox Code Playgroud)

用户类;

@Component
@Entity
public class Users {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public long id;
    public String username;
    public String mail;

    @Temporal(TemporalType.DATE)
    public Date enrolment_date;

    @ManyToOne(cascade = CascadeType.ALL)
    public Domains domains;

    @ManyToOne(cascade = CascadeType.ALL)
    public Positions positions;

    @OneToMany(targetEntity = UserLanguages.class, mappedBy = "users", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    public Set<UserLanguages> userlanguages = new HashSet<UserLanguages>();

    @OneToMany(targetEntity = UserCertificates.class, mappedBy = "users", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    public Set<UserCertificates> usercertificates = new HashSet<UserCertificates>();

    @OneToMany(targetEntity = UserKnowledge.class, mappedBy = "users", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    public Set<UserKnowledge> userknowledge = new HashSet<UserKnowledge>();
Run Code Online (Sandbox Code Playgroud)

"使用不同实体进行托管映射"的含义是什么?我研究了这个错误消息,但我想没有人得到这个错误.休眠-ORM

naX*_*aXa 8

此错误消息表明Hibernate已检测到无效的"托管实体" - >"托管实体"映射,其中key!= value.

MergeContext存储管理实体到合并实体的映射(反之亦然),我猜你有两个不同的托管实体同时加载,表示数据库中的相同记录(这就是为什么你可以得到这个错误).(来源:Hibernate Core分析的内部源代码)

从提供的示例中很难说另一个Users实体是什么.所以我在这里写一些想法:

  • Users实体可以被定义Domains,Positions,UserLanguages,UserCertificates,或UserKnowledge类.如果你在CascadeType.ALL/ 找到它CascadeType.PERSIST,删除cascade属性.

  • 如果您正在某个地方使用Users集合中的实体并尝试保留它,您可能也会遇到此错误.覆盖equals()和类的hashCode()方法Users并使用a Set来确保对象的唯一性.该equals()方法可能与比较id一样简单:

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
    
        Users that = (Users) o;
    
        return getId() == that.getId();
    }
    
    @Override
    public int hashCode() {
        return Long.valueOf(getId()).hashCode();
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 仔细Users查看程序中的其他实体,并session.evict(users)从会话缓存中删除对象实例.