关于Java:多次调用jpa repository.save()会引发异常

Calling jpa repository.save() multiple times throws exception

我想多次调用jpa repository.save。

但是当我第二次尝试保存对象时,它会抛出PersistentObjectException并说已将分离的实体传递给持久化。

代码和异常如下。我想念什么?

1
2
3
4
5
6
7
8
9
10
11
public void createGame(GameTeamRequest gameTeamRequest) {
        for(Entry<String, Integer> hm : gameTeamRequest.getTeamsInnigsPostionMap().entrySet()) {
            GameTeam gameTeam = new GameTeam();
            Team team = new Team();
            team.setTeamName(hm.getKey());
            gameTeam.setTeam(team);
            gameTeam.setGame(gameTeamRequest.getGame());
            gameTeam.setInningsPosition(hm.getValue());
            gameTeamRepository.save(gameTeam);
        }
    }

例外如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
SEVERE: Servlet.service() for servlet [appServlet] in context with path [/iscorecard] threw exception [Request processing failed; nested exception is org.springframework.dao.InvalidDataAccessApiUsageException: detached entity passed to persist: com.dragonfly.iscorecard.domain.Game; nested exception is org.hibernate.PersistentObjectException: detached entity passed to persist: com.dragonfly.iscorecard.domain.Game] with root cause
org.hibernate.PersistentObjectException: detached entity passed to persist: com.dragonfly.iscorecard.domain.Game
    at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:141)
    at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:842)
    at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:835)
    at org.hibernate.engine.spi.EJB3CascadingAction$1.cascade(EJB3CascadingAction.java:52)
    at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:387)
    at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:330)
    at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:208)
    at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:165)
    at org.hibernate.event.internal.AbstractSaveEventListener.cascadeBeforeSave(AbstractSaveEventListener.java:424)
    at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:263)
    at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:192)
    at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:135)
    at org.hibernate.ejb.event.EJB3PersistEventListener.saveWithGeneratedId(EJB3PersistEventListener.java:78)
    at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:208)
    at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:151)
    at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:78)
    at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:852)
    at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:826)
    at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:830)
    at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:865)

游戏类别:

1
2
3
4
5
6
7
8
9
10
11
  @Entity
@Table(name ="GAME")

public class Game extends Model {

@Column(name ="TOURNAMENT_ID")
private String tournamentId;

@OneToMany(mappedBy ="game")
private Set<GameTeam> gameTeam;          
}

班级:

1
2
3
4
5
6
7
8
9
10
11
12
    @Entity
@Table(name ="TEAM")

    public class Team extends Model {

    @Column(name ="TEAM_NAME")
    private String teamName;

    @OneToMany(mappedBy ="game")
    private Set<GameTeam> gameTeam;

}

GameTeam:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    @Entity
@Table(name ="GAME_TEAM")

    public class GameTeam extends Model {

    @ManyToOne(cascade = { CascadeType.PERSIST, CascadeType.MERGE })
    @JoinColumn(name ="GAME_ID")
    private Game game;

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name ="TEAM_ID")
    private Team team;

    @Column(name ="INNINGS_POSITION")
    private int inningsPosition;

}


该异常引用了Game对象,因此您似乎将一个独立的Game设置为第二个GameTeam。
您可以通过添加(至少)

来解决此问题

1
 cascade = { CascadeType.PERSIST, CascadeType.MERGE }

到您的映射。