2013-05-01 2 views
3

У меня есть класс Challenge, который имеет отношение много к одному с классом User. Это однонаправленный, так это выглядит следующим образом:Весна данных JPA вызывает EntityExistsException с каскадным сохранением

@Entity 
@Table(name = "UserTable") 
public class User { 
    @Id 
    private String userId; 
} 

@Entity 
@Table(name = "ChallengeTable") 
public class Challenge { 
    @Id 
    private String challengeId; 

    @ManyToOne(fetch = FetchType.EAGER, cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH}) 
    @JoinColumn(name = "userId") 
    private User user; 
} 

Я использую Spring Data JPA, и когда я использую save метод из CRUDRepository на Challenge объекта, я хочу, чтобы упорствовать прилагаемую пользователю, если пользователь еще не существует и объединяет пользователя в старый пользователь, если он уже существует.

Я использую метод findOne(String id) в UserRepository, чтобы получить пользователь, используя userId, и это пользователь я устанавливаю в Challenge.

Она каскады прекрасно, если пользователь не существует, но когда я пытаюсь сохранить его с предварительно существующим пользователем я получаю исключение:

javax.persistence.EntityExistsException: a different object with the same identifier value was already associated with the session: [com.mywebsite.model.User#zk9moo78sx685g6o9yphegdx6lpoll9x] 

я не уверен, что я я делаю неправильно здесь. Изменение CascadeType на ALL ничего не меняет. Пытаться полностью удалить CascadeType и вручную сохранить пользователя сначала тоже не работает. Это дает мне ошибку:

org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing: com.mywebsite.model.Challenge.user -> com.mywebsite.model.User 

Это кажется, имеет место, когда выходит из сделки (как у меня есть класс обслуживания слой с аннотацией @Transactional).

Если я вынимаю аннотацию @Transactional и сохраняю ее вручную, кажется, все работает нормально. (Я все еще хочу, чтобы каскадное сохраняет и операции на уровне услуг, хотя.)

Достав @Transactional и пытаются использовать каскадный сохраняет сбой с SQLIntegrityConstraintViolationException исключения, потому что кажется, что User становится отдельностоящим лицом и пытается сохраняться он заново, но этот первичный ключ уже существует, поэтому он терпит неудачу.

Может ли кто-нибудь помочь мне понять, что здесь происходит, и помочь мне получить каскадное сохранение работы с транзакциями в Spring Data JPA?

+0

Можете ли вы опубликовать свой метод обслуживания? – lunr

+0

У вас есть методы hashcode и equals, созданные для сущностей? –

+0

Мне не хватало hashcode и равнялось на двух сущностях, но исправление не помогло решить проблему. – CorayThan

ответ

0

Я пробовал использовать каскадные параметры, связанные с гибернацией, и все остальное, о чем я мог подумать, но я не мог получить каскадные сбережения, чтобы работать как Hibernate CascadeType.SAVE_UPDATE. Я считаю, что это жесткое ограничение JPA с данными Spring.

Вместо этого я добавил слой между сервисом и репозиторием интерфейса. Он сохраняет зависимый объект (пользователь), затем вызов.