2014-12-27 2 views
9

я получаю эту ошибку при отправке формы:Частный объект передается упорствовать ошибку

org.hibernate.PersistentObjectException: отдельностоящий объект передается упорствовать: 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> 

Что я делаю неправильно?

ответ

20
teamService.save(team); 

Метод сохранения принимает только переходные объекты. Что такое переходный объект, который вы можете найти

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

Вы получаете объект команды, и вы пытаетесь упорствовать его к БД, но этот объект имеет объект учетной записи в нем и что объект Account отсоединяется (средство этот экземпляр этого объекта был сохранен в БД, но этот объект не находится в сеансе). Hibernate пытается спасти его из-за вы указали:

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

Итак, есть несколько способов, как вы можете это исправить:

1) не использует конфигурацию CascadeType.ALL. Объект учетной записи может использоваться для количества команд (по крайней мере, это позволяет доменная структура), и операция обновления может обновлять учетную запись для ВСЕХ команд - это означает, что эту операцию не следует инициировать с обновлением Team. Я бы отключил параметр каскада (значение по умолчанию не является каскадным), если вам действительно нужна конфигурация MERGE/DELETE. Но если вам действительно нужно это сохранить, см. Опцию # 2

2) вместо 'save()' использовать метод saveOrUpdate() '. Метод saveOrUpdate() принимает временные и отдельные объекты. Но проблема с этим подходом в дизайне: действительно ли вам нужно вставлять/обновлять учетную запись при сохранении объекта Team? Я бы разделил его на две операции и не смог обновить Аккаунт от Команды.

Надеюсь, это поможет.

+0

Голосовать за первое решение, которое мне помогло. – vtomic85

10

Ошибка возникает, потому что установлен id. Спящий режим различает переходные и удаленные объекты и продолжает работать только с переходными объектами.

isteamService.save(team); 

в этой операции не может быть загружен, потому что идентификатор является @GeneratedValue

+1

Thats the perfext answer, убедитесь, что id не имеет значения. –

+1

Ой, поэтому объекты с идентификатором, который имеет '@ GeneratedValue', даже не могут быть сохранены, если этот идентификатор уже установлен? Я думал, что аннотация будет просто своего рода резервным. Приятно знать, что это не так! – Froxx

+1

Убедитесь, что ваш идентификатор не установлен в 0, если ваш тип данных является «Целочисленным», и это нормально, если тип данных id «int». – Ram

0

Так как ваш идентификатор автоматически сгенерированное значение, не отправить его со стороны клиента.У меня была такая же проблема. Убедитесь, что вы не указали значение для автоматически генерируемого атрибута.

Смежные вопросы