Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

@ManyToOne unidirectional mapping

I have an Entity class Payment which has Entity class PaymentMethod with Many to one relationship.

Now since My PaymentMethod is master table.

So i want to save payment without effecting the master table PaymentMethod.

But every time i save the Payment it insert new row in PaymentMethod to. I unable to figure out why.

I m using SpringData save.

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

After payment get save PAYMENT_METHOD entry with duplicate name ?

I am unable to figure out why?

For saving i have created simple CRUDRepository for Payment type

calling save entity of repository.

Please suggest where i am falling out.

whenever code executes this line :

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

It gives error as

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)

I am unable to figure out how the code if trying to flush it when i call finder method from repository.

Is i am missing something?

Issue solved thanks @JB and @spiritwalker , But unable to find the exact root cause , so just discussing the behavior may be the discussion will add on too 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
like image 840
Zuned Ahmed Avatar asked Feb 17 '13 09:02

Zuned Ahmed


2 Answers

Start by removing the cascades, since you precisely don't want to create/modify the PaymentMethod when you create/modify a Payment.

Then, when you create a Payment, assign it the existing PaymentMethod you want it to be associated with:

PaymentMethod existingPaymentMethod = em.find(PaymentMethod.class, idOfThePaymentMethod);
Payment payment = new Payment();
payment.setPaymentMethod(existingPaymentMethod);
em.persist(payment);
like image 176
JB Nizet Avatar answered Oct 15 '22 15:10

JB Nizet


remove cascade={CascadeType.REFRESH,CascadeType.MERGE,CascadeType.PERSIST} from your Payment entity.

Since PaymentMethod is a master table like you said, you do not want to have any cascading operation happens from Payment down to PaymentMethod.

like image 34
spiritwalker Avatar answered Oct 15 '22 15:10

spiritwalker