2013-02-17 2 views
5

나는 Entity 클래스 많은 관계 하나와 PAYMENTMETHOD이있는 엔티티 클래스 지불 있습니다.@ManyToOne 단방향 매핑

이제 My PaymentMethod가 마스터 테이블이므로.

그래서 마스터 테이블 PaymentMethod에 영향을주지 않고 지불을 저장하려고합니다.

하지만 결제를 저장할 때마다 PaymentMethod에 새 행이 삽입됩니다. 나는 이유를 알 수 없었다.

스프링 데이터 저장을 사용합니다.

Payment.java

@Entity 
@Table(name="payment") 
public class Payment implements Serializable { 
    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private Long id; 

    @ManyToOne(cascade={CascadeType.REFRESH,CascadeType.MERGE,CascadeType.PERSIST}) 
    @JoinColumn(name="payment_method_id") 
    private PaymentMethod paymentMethod; 

    //getter and setters 
} 

PaymentMethod.java

@Table(name="paymentmethod") 
public class PaymentMethod implements Serializable { 
@Id 
@GeneratedValue(strategy = GenerationType.AUTO) 
private Long id; 

@Column(name="name",unique=true ,nullable=false) 
private String name; 

//GETTER AND SETTERS 
} 

PAYMENT_METHOD DATA

ID | NAME 
1 | AA 
2 | BB 
3 | CC 

결제 후 중복 이름이있는 PAYMENT_METHOD 항목을 저장 하시겠습니까?

이유를 파악할 수 없습니까? 내가 저장소의 실체 저장 호출 지불 유형

에 대한 간단한 CRUDRepository을 만든 저장하는

.

내가 어디 떨어지는 지 제안하십시오. 코드이 줄을 실행 할 때마다

는 :

paymentMethodRepository.findByName(payment.getPaymentMethod().getName()); 

내가 알아낼 수 없습니까

Caused by: org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing: com.enrollment.domain.Payment.paymentMethod -> com.enrollment.domain.PaymentMethod 
    at org.hibernate.engine.spi.CascadingAction$8.noCascade(CascadingAction.java:380) 
    at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:176) 
    at org.hibernate.event.internal.AbstractSaveEventListener.cascadeBeforeSave(AbstractSaveEventListener.java:423) 
    at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:264) 
    at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:193) 
    at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:136) 
    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.internal.SessionImpl.firePersistOnFlush(SessionImpl.java:870) 
    at org.hibernate.internal.SessionImpl.persistOnFlush(SessionImpl.java:863) 
    at org.hibernate.engine.spi.CascadingAction$8.cascade(CascadingAction.java:346) 
    at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:380) 
    at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:323) 
    at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:208) 
    at org.hibernate.engine.internal.Cascade.cascadeCollectionElements(Cascade.java:409) 
    at org.hibernate.engine.internal.Cascade.cascadeCollection(Cascade.java:350) 
    at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:326) 
    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.cascadeAfterSave(AbstractSaveEventListener.java:448) 
    at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:293) 
    at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:193) 
    at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:136) 
    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.internal.SessionImpl.firePersistOnFlush(SessionImpl.java:870) 
    at org.hibernate.internal.SessionImpl.persistOnFlush(SessionImpl.java:863) 
    at org.hibernate.engine.spi.CascadingAction$8.cascade(CascadingAction.java:346) 
    at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:380) 
    at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:323) 
    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.cascadeAfterSave(AbstractSaveEventListener.java:448) 
    at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:293) 
    at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:193) 
    at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:136) 
    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.internal.SessionImpl.firePersistOnFlush(SessionImpl.java:870) 
    at org.hibernate.internal.SessionImpl.persistOnFlush(SessionImpl.java:863) 
    at org.hibernate.engine.spi.CascadingAction$8.cascade(CascadingAction.java:346) 
    at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:380) 
    at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:323) 
    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:423) 
    at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:264) 
    at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:193) 
    at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:136) 
    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.internal.SessionImpl.firePersistOnFlush(SessionImpl.java:870) 
    at org.hibernate.internal.SessionImpl.persistOnFlush(SessionImpl.java:863) 
    at org.hibernate.engine.spi.CascadingAction$8.cascade(CascadingAction.java:346) 
    at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:380) 
    at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:323) 
    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:423) 
    at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:264) 
    at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:193) 
    at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:136) 
    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.internal.SessionImpl.firePersistOnFlush(SessionImpl.java:870) 
    at org.hibernate.internal.SessionImpl.persistOnFlush(SessionImpl.java:863) 
    at org.hibernate.engine.spi.CascadingAction$8.cascade(CascadingAction.java:346) 
    at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:380) 
    at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:323) 
    at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:208) 
    at org.hibernate.engine.internal.Cascade.cascadeCollectionElements(Cascade.java:409) 
    at org.hibernate.engine.internal.Cascade.cascadeCollection(Cascade.java:350) 
    at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:326) 
    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.AbstractFlushingEventListener.cascadeOnFlush(AbstractFlushingEventListener.java:160) 
    at org.hibernate.event.internal.AbstractFlushingEventListener.prepareEntityFlushes(AbstractFlushingEventListener.java:151) 
    at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:88) 
    at org.hibernate.event.internal.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListener.java:58) 
    at org.hibernate.internal.SessionImpl.autoFlushIfRequired(SessionImpl.java:1186) 
    at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1241) 
    at org.hibernate.internal.QueryImpl.list(QueryImpl.java:101) 
    at org.hibernate.ejb.QueryImpl.getSingleResult(QueryImpl.java:285) 

같은 오류를 제공하는 방법 코드 내가 저장소에서 파인더 메소드를 호출 할 때를 씻어하려고하는 경우.

내가 누락 된 항목이 있습니까?

문제 해결 감사 @JB 및 @spiritwalker, 그러나 정확한 근본 원인을 찾을 수없는, 그래서 바로 행동을 토론하는 것은 토론이 너무 knowledege를에 추가 할 수 있습니다.

Behaviour .. 

Open Transaction 
    1. validate 
    2. save child 
    3. validate and update 
    4. save parent 
Close Transaction 

it was giving above error. 

Now, after code change it worked 

Open Transaction 
    1. validate 
    2. validate and update 
    3. save child 
    4. save parent 
Close Transaction 
+1

문제는 3 단계에서, 당신은 데이터베이스 쿼리를 실행하고 있다는 것입니다. 따라서 Hibernate는 메모리를 실행하기 전에 메모리 내 변경을 플러시하여 메모리에 저장된 새로운 값을 쿼리가 볼 수 있지만 아직 데이터베이스에 저장하지는 못하게한다. 메모리 내 상태가 유효하지 않기 때문에이 예외가 발생합니다. –

+0

맞습니다.하지만 여전히 트랜잭션 (readonly = false)이므로 선택 쿼리를 실행할 때 플러시가 발생해서는 안됩니다. [참고 : 마스터 데이터에 대해 select가 실행되었습니다.] –

+0

아니, 나는 그렇게 생각하지 않는다. 거래에서 많은 지불을 생성하고 나중에 동일한 거래에서 주어진 유형의 모든 지불을 나열하려고한다고 가정합니다. 방금 작성한 지불이 결과에 포함되도록 (JDBC를 사용하여 지불을 삽입 한 경우와 마찬가지로) 분명히 원하십시오. 그래서 세션이 플러시됩니다. –

답변

2

당신의 지불 엔티티로부터 캐스케이드 = {CascadeType.REFRESH, CascadeType.MERGE, CascadeType.PERSIST}를 제거합니다.

PaymentMethod는 앞에서 말한 것처럼 마스터 테이블이므로 PaymentMethod까지 계단식 작업을 수행하지 않으려합니다.

+0

제거하려고하는 분리 된 엔티티를 말하면 제거합니다. –

+0

PaymentMethod 엔티티 인스턴스를 검색하여 Payment 엔티티에 할당해야합니다. – spiritwalker

+0

그랬다면 똑같은 –

3

시작 당신이 지불을 수정/만들 때 정확하게 PAYMENTMETHOD을 생성/수정하지 않기 때문에, 캐스케이드를 제거하여.그런 다음

, 당신이 지불을 만들 때, 당신은 그것과 연관 될하려는 기존 PAYMENTMETHOD 할당 :

PaymentMethod existingPaymentMethod = em.find(PaymentMethod.class, idOfThePaymentMethod); 
Payment payment = new Payment(); 
payment.setPaymentMethod(existingPaymentMethod); 
em.persist(payment); 
+0

spring 저장소는 id가 null 인 경우 내부적으로 동일한 작업을 수행하는 save 메소드를 제공합니다. –

+0

null 인 id는 무엇입니까? 스프링 저장소는 당신이 그에게주는 물건을 가져 간다. 기존 PaymentMethod를 제공하는 대신 새 PaymentMethod를 제공하면 원하는대로 작동하지 않습니다. –

+0

올바른 개체를 설정 한 후에도 같은 방식으로 작동합니다. 이유를 알아낼 수 없습니까? –

관련 문제