Hi, I was hoping someone could help shed some light on the following issue. 

(I am using OpenEJB 4.6.1-SNAPSHOT)

I have a problem when trying to save a bean that has child elements 
(relationships to other tables). The problem occurs when I want to create a 
completely new record with completely new child records. The problem is that 
when the JPA provider gets to work and starts calling INSERT statements, the 
order in which it does so seems to be random. And thus on certain occasions it 
tries to call the INSERT statement of the child bean first before the parent 
which will throw an SQL error (‘foreign key constraint fails’ error).

It occurs when I call a rest method which will save the bean. I’m assuming a 
transaction is opened at the start of the method and committed and the end.

To illustrate, take a look at the code below (which resembles my scenario). 
Basically I have a rest method (which tries to save a bean with child beans 
which are all new records). I’m wondering if it has something to do with my 
cascade annotations? Is there some way to tell the JPA provider to call the 
INSERT statements in order from parent down to child  (in that order)?

@Stateless
@Path(“/example")
@Consumes({MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_JSON})
public class ExampleAPI {

        @Path(“/save”)
        public void create(String name) {
                Person person = new Person(name);

                Car car = new Car();

                car.addWheel(new Wheel());
                car.addWheel(new Wheel());

                person.addCar(car);

                entityManager.persist(person); // throws error
        }

}

public class Person {

        @OneToMany(mappedBy = "person", fetch = FetchType.EAGER, cascade = 
CascadeType.PERSIST)
        private List<Car> cars;
        
        public void addCar(Car car) {
                car.setPerson(this);
                this.cars.add(car);
        }
}

public class Car {
        
        @ManyToOne(cascade = CascadeType.PERSIST)
        @JoinColumn(name = "personId")
        private Person person;

        @OneToMany(mappedBy = "car", fetch = FetchType.EAGER, cascade = 
CascadeType.PERSIST)
        private List<Car> wheels;

        public void setPerson(Person person) { this.person = person; }

        public void addWheel(Wheel wheel) {
                wheel.setCar(this);
                this.wheels(wheel);
        }
        
}

public class Wheel {

        @ManyToOne(cascade = CascadeType.PERSIST)
        @JoinColumn(name = "carId")
        private Car car;

        public void setCar(Car car) { this.car = car; }
}

Reply via email to