web-dev-qa-db-ja.com

子データを保存するときに永続化するために渡される分離されたエンティティ

フォームを送信するとこのエラーが発生します。

org.hibernate.PersistentObjectException:persistに渡された分離されたエンティティ:com.project.pmet.model.Account;ネストされた例外はjavax.persistence.PersistenceException:org.hibernate.PersistentObjectException:永続化に渡された分離されたエンティティ: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;

    ...

チーム:

@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;

    ...

コントローラーの一部を次に示します。

    @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";
    }

そして、フォーム:

<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>

私は何を間違えていますか?

14
keysersoze
_teamService.save(team);
_

Saveメソッドは一時オブジェクトのみを受け入れます。あなたが見つけることができる一時的なオブジェクトは何ですか here

Transient - an object is transient if it has just been instantiated using the new operator, and it is not associated with a Hibernate Session. It has no persistent representation in the database and no identifier value has been assigned. Transient instances will be destroyed by the garbage collector if the application does not hold a reference anymore. Use the Hibernate Session to make an object persistent (and let Hibernate take care of the SQL statements that need to be executed for this transition).

Teamオブジェクトを取得し、それをDBに永続化しようとしていますが、そのオブジェクトにはAccountオブジェクトがあり、そのAccountオブジェクトは切り離されています(つまり、そのオブジェクトのインスタンスはDBに保存されていますが、そのオブジェクトはセッションにありません)。あなたが指定したため、Hibernateはそれを保存しようとしています:

_@OneToMany(cascade = CascadeType.ALL, ....
_

そのため、修正方法はいくつかあります。

1)CascadeType.ALL構成を使用しないでください。アカウントオブジェクトは多くのチームに使用でき(少なくともドメイン構造で許可されます)、更新操作はすべてのチームのアカウントを更新する可能性があります。つまり、この操作はチーム更新で開始しないでください。 MERGE/DELETE構成を本当に使用する必要がある場合は、そこからカスケードパラメーターを削除します(デフォルト値はカスケード操作なしです)。しかし、本当に永続化する必要がある場合は、オプション#2を参照してください

2)「save()」の代わりに「saveOrUpdate()」メソッドを使用します。 'saveOrUpdate()'メソッドは、一時オブジェクトと分離オブジェクトを受け入れます。しかし、このアプローチの問題は設計にあります。Teamオブジェクトを保存するときに本当にアカウントを挿入/更新する必要がありますか?これを2つの操作に分割し、チームからアカウントを更新しないようにします。

お役に立てれば。

33
Ilya Ovesnov

idが設定されているため、エラーが発生します。 Hibernateは一時オブジェクトと分離オブジェクトを区別し、永続オブジェクトは一時オブジェクトでのみ機能します。

isteamService.save(team);

@GeneratedValueであるため、この操作ではidをロードできません

12
borchvm

Idは自動生成された値であるため、クライアント側から送信しないでください。同じ問題がありました。自動生成された属性の値を指定しないようにしてください。

0
Pubudu