0

I have two tables 'STUDENT'(pk - student_id autogenerated) and 'Address' . address_id is pk of Address table and it must be same value as student_id .

entities :

@Entity
@Table(name = "student")
Public class Student{

    @Id
    @GeneratedValue
    @Column(name = "STUDENT_ID",updatable = false,insertable = false)
    private long Id;


    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name="STUDENT_ID")
    private Address address;

.....
//getters setters
}


@Entity
@Table(name = "address")
Public class Address{

    @Id
    @Column(name = "ADDRSS_ID",updatable = false,insertable = false)
    private long Id;


    @OneToOne
    private Student student;

.....
//getters setters
}



service 

public class Service {

 @Autowired StudentRepository repo;

 public void saveStudent(Student s){

 repo.save(s)
}

}

Problem that i am facing is because of cascade.ALL JPA trying to save child entity i.e. Address before parent entity Student, but ADDRESS_ID is having NOT NULL Constraint and I am getting Constraint Violation Exception. How to Save both at one go. PLEASE Help . Thanks in advance

Atul
  • 521
  • 1
  • 7
  • 20
  • Well, as you already found out, you can't do it in one go. `Student` must be inserted first to generate the ID, only then you can save the address. Also, you probably want `insertable = true` – XtremeBaumer Nov 28 '22 at 15:37
  • 1
    @XtremeBaumer kindly disagree, actually the mechanism is very straight forward to persist entities which have one-to-one association and cascading with in one transaction, deferable constraint can be very handy in this cases. – Lunatic Nov 28 '22 at 22:59
  • An answer provided, if it suits you requirement please consider to upvote and accept it cause it take considerable time from me, otherwise feel free to leave comment, i will gladly be here to help you. – Lunatic Nov 28 '22 at 23:00
  • @Lunatic one transaction sure, but not a single call to `repo.save()` which then should save both entities, which is what OP is actually asking for. It is possible if both entities have generated identifiers, but not as OP has it set up – XtremeBaumer Nov 30 '22 at 07:21
  • 1
    Also from what I could find, deferred constraints seems to be Postgres specific which might not work for OP – XtremeBaumer Nov 30 '22 at 07:27

1 Answers1

0

you asked

How to Save both (entity and associated entity) at one go.

Let just translate "one go" as a one transaction, they are many ways to achieve it all of them lay in the fact that for persisted entity flushing being done at proper point of time before committing the whole transaction.

Solution

One practice is adopt a behind cache mechanism upon JPA specifications and having deferable constraint. persist Student and Address entity first to obtain an id from generator from database with flushing, then create proper binding and association between them and finally commit the transaction.

To demonstrate it, begin with session abstraction i.e EntityManager which stands as first level cache and you can instantiate it via EntityManagerFactory which indeed stands for second level cache.

EntityManager entityManager = entityManagerFactory.createEntityManager();
entityManager.getTransaction().begin();
entityManager.persist(Not_associated_entities);
...
flush();
...
entityManager.merge(associated_entities);
...
entityManager.getTransaction().commit();
entityManager.close();

Also specifically for PK and FK columns are most often indexed, so sharing the PK can reduce the index footprint by half, which is desirable since you want to store all your indexes into memory to speed up index scanning, you may for OneToOne association optimization in this article.

Caution

Always close all the manual instantiation of entityManager.

Unmitigated
  • 76,500
  • 11
  • 62
  • 80
Lunatic
  • 1,519
  • 8
  • 24