lm2a
lm2a

Reputation: 915

Bidirectional @OneToOne persistence

I am starting with JPA and EclipseLink and did some experiments. But results are a little unexpected for my understanding. Here for example I have a bidirectional relation between two entities:

@Entity
@Table(name = "student")
public class Student {
 
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
 
    private String name;
 
    @OneToOne(mappedBy = "student", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
    private Tuition tuition;

@Entity
@Table(name = "tuition")
public class Tuition {
 
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
 
    private Long fee;
 
    // Que columna en la tabla Tuition tiene la FK
    @JoinColumn(name = "student_id")
    @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    private Student student;

I have created two tests to check persisting both entities from both sides. When I try to persist from one side it works OK, both entities are persisted. But when trying to do the same from the other side Student in Tuition have a null value

Here are the tests:

@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class Jpa1to1Bidireccional {

    private static final String PERSISTENCE_UNIT_NAME = "JPA_PU";
    private EntityManagerFactory factory;

    @Before
    public void init() throws Exception {
        factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
    }

    @Test
    public void testCase_1() {
        System.out.println("Testcase_1 executes");
        EntityManager em = factory.createEntityManager();

        // Begin a new local transaction so that we can persist a new entity
        em.getTransaction().begin();

        Student s = new Student();
        s.setName("Pirulo");
        Tuition t = new Tuition();
        t.setFee(2134L);
        s.setTuition(t);

        em.persist(s);

        // Commit the transaction, which will cause the entity to // be stored in the
        // database
        em.getTransaction().commit();
        em.close();
    }

    @Test
    public void testCase_2() {
        System.out.println("Testcase_2 executes");
        EntityManager em = factory.createEntityManager();

        em.getTransaction().begin();

        Student s = new Student();
        s.setName("Cachilo");
        Tuition t = new Tuition();
        t.setFee(3134L);
        t.setStudent(s);

        em.persist(t);
        em.getTransaction().commit();
        em.close();
    }

enter image description here

enter image description here

Any help to understand what is going on, will be very welcomed. Regards,

Upvotes: 0

Views: 75

Answers (1)

johnnyutts
johnnyutts

Reputation: 1452

In your first case you are persisting student and then cascading a save to tuition but tuition has no student. You need to keep bidirectional relationships in sync before persisting

Second case you persist tuition and it requires fk of student so it cascade persist student first

Upvotes: 1

Related Questions