Java 保存子数据时传递给持久化的分离实体

Java 保存子数据时传递给持久化的分离实体,java,spring,hibernate,cascade,persistent,Java,Spring,Hibernate,Cascade,Persistent,我在提交表单时遇到以下错误: <form:form commandName="team" id="teamForm"> <div class="form-group"> <label>Name</label> <form:input path="name" cssClass="form-control" /> </div> <div class

我在提交表单时遇到以下错误:

<form:form commandName="team" id="teamForm">
      <div class="form-group">
          <label>Name</label>
          <form:input path="name" cssClass="form-control" />
      </div>
      <div class="form-group" id="row-template">
          <label>Members</label>
          <form:select path="members[0].id" cssClass="form-control" data-live-search="true" >
             <form:options items="${accounts}" itemValue="id" />
          </form:select>
          ...
      </div>
   <form:hidden path="owner.id" />
</form:form>
org.hibernate.PersistentObjectException:传递给persist的分离实体:com.project.pmet.model.Account;嵌套异常为javax.persistence.PersistenceException:org.hibernate.PersistentObjectException:传递给persistent的分离实体:com.project.pmet.model.Account

以下是我的实体:

账户:

@Entity
@DynamicInsert
@DynamicUpdate
public class Account {

    @Id
    @GeneratedValue
    private Integer id;

    @Column(nullable = false)
    private String login;

    @Column(nullable = false)
    private String password;

    @Column(nullable = false)
    private String email;

    @ManyToOne
    @JoinColumn(name = "team_id")
    private Team team;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "owner")
    private List<Team> ownedTeams;

    ...
@实体
@动态服务器
@动态铜日期
公共类帐户{
@身份证
@生成值
私有整数id;
@列(nullable=false)
私有字符串登录;
@列(nullable=false)
私有字符串密码;
@列(nullable=false)
私人字符串电子邮件;
@许多酮
@JoinColumn(name=“团队id”)
私人团队;
@OneToMany(cascade=CascadeType.ALL,mappedBy=“owner”)
私有列表拥有的团队;
...
团队:

@Entity
@DynamicInsert
@DynamicUpdate
public class Team {

    @Id
    @GeneratedValue
    private Integer id;

    @Column(nullable = false)
    private String name;

    @ManyToOne
    @JoinColumn(name = "owner_id", nullable = false)
    private Account owner;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "team")
    private List<Account> members;

    ...
@实体
@动态服务器
@动态铜日期
公开课小组{
@身份证
@生成值
私有整数id;
@列(nullable=false)
私有字符串名称;
@许多酮
@JoinColumn(name=“owner\u id”,nullable=false)
私人帐户所有者;
@OneToMany(cascade=CascadeType.ALL,mappedBy=“团队”)
非公开名单成员;
...
以下是控制器的一部分:

    @ModelAttribute("team")
    public Team createTeamObject() {
        return new Team();
    }

    @RequestMapping(value = "/teams/create-team", method = RequestMethod.GET)
    public String getCreateTeam(@ModelAttribute("team") Team team, Principal principal) {
        logger.info("Welcome to the create team page!");

        Account owner = accountService.findOneByLogin(principal.getName());
        team.setOwner(owner);
        team.setMembers(new AutoPopulatingList<Account>(Account.class));

        return "teams";
    }

    @RequestMapping(value = "/teams/create-team", method = RequestMethod.POST)
    public String postCreateTeam(@ModelAttribute("team") Team team) {
        logger.info("Team created!");

        teamService.save(team);

        return "redirect:/teams.html";
    }
@modeldattribute(“团队”)
公共团队createTeamObject(){
返回新团队();
}
@RequestMapping(value=“/teams/create team”,method=RequestMethod.GET)
公共字符串getCreateTeam(@ModelAttribute(“团队”)团队,主体){
info(“欢迎来到创建团队页面!”);
帐户所有者=accountService.findOneByLogin(principal.getName());
团队。集合所有者(所有者);
team.setMembers(新的AutoPopulatingList(Account.class));
返回“团队”;
}
@RequestMapping(value=“/teams/create team”,method=RequestMethod.POST)
公共字符串postCreateTeam(@ModelAttribute(“团队”)团队){
logger.info(“团队创建!”);
teamService.save(团队);
返回“重定向:/teams.html”;
}
及表格:

<form:form commandName="team" id="teamForm">
      <div class="form-group">
          <label>Name</label>
          <form:input path="name" cssClass="form-control" />
      </div>
      <div class="form-group" id="row-template">
          <label>Members</label>
          <form:select path="members[0].id" cssClass="form-control" data-live-search="true" >
             <form:options items="${accounts}" itemValue="id" />
          </form:select>
          ...
      </div>
   <form:hidden path="owner.id" />
</form:form>

名称
成员
...
我做错了什么

teamService.save(team);
Save方法只接受临时对象。您能找到的临时对象是什么

Transient-如果一个对象刚刚使用新操作符实例化,并且没有与Hibernate会话关联,那么它就是Transient。它在数据库中没有持久表示,也没有分配标识符值。如果应用程序不持有refe,则垃圾回收器将销毁临时实例使用Hibernate会话使对象持久化(并让Hibernate处理此转换需要执行的SQL语句)。

您正在获取团队对象,并试图将其持久化到数据库中,但该对象中包含Account对象,并且该Account对象已分离(表示该对象的实例已保存到数据库中,但该对象不在会话中)。Hibernate正试图保存它,因为您已指定:

@OneToMany(cascade = CascadeType.ALL, ....
因此,有几种方法可以修复它:

1) 不要使用CascadeType.ALL configuration.Account对象可用于多个团队(至少域结构允许),并且更新操作可能会更新所有团队的帐户--这意味着不应使用团队更新启动此操作。 如果您真的需要使用合并/删除配置,我会从中删除cascade参数(默认值为no cascade operations)

2) 使用“saveOrUpdate()”方法而不是“save()”。“saveOrUpdate()”方法接受暂时和分离的对象。 但这种方法的问题是在设计中:在保存团队对象时是否真的需要插入/更新帐户?我会将其分为两个操作,并阻止团队更新帐户


希望这有帮助。

发生错误是因为设置了id。Hibernate区分瞬时对象和分离对象,而persist仅适用于瞬时对象

isteamService.save(team);

在此操作中无法加载id,因为它是@GeneratedValue

因为您的id是自动生成的值,所以不要从客户端发送它。我遇到了相同的问题。请确保您没有为自动生成的属性提供值。

请将@OneToMany(cascade=CascadeType.ALL,…)更改为@OneToMany(cascade=CascadeType.REMOVE,…)或者除了CascadeType.PERSIST之外的其他方法。如果问题已经解决,请确保id没有值。哦,如果id具有
@GeneratedValue
的id,那么即使该id已设置,也无法保存该对象?我认为该注释只是某种回退。很高兴知道不是这样!确保您的id不存在如果您的数据类型是
Integer
,则设置为0;如果id数据类型是
int
,则设置为0。这是最简单的答案,也是我的关键:id有一个生成策略,我正在设置它!