'Adding and retrieving the data from relational database using spring data jpa

I am using spring data jpa

I have two tables person, order

Both have relationship like one to many from person to order order(person_id) -> person(id)

create table person (id int primary key, name varchar(20));
create table order (id int primary key, name varchar(20), person_id foreign key references person(id));

Consider i have schema in place for both tables and there is no data yet. I need to insert this data -

Person  {name: "person1"}
Order {name: "order1", person_id: <corresponding to person1 record>}

Does inserting the data related by foreign key needs two calls to db?

  1. saving the person
  2. take the primary key from the saved person entity (step 1) then save Order?
    Person person = new Person("person1");
    Person person = personRepository.save(person);
    
    Order order = new Order("order1");
    order.setPersonId(person.getId());
    orderRepository.save(order);

Or is there any alternative to save data to two tables using single call to db?

Retrieving the data If i need to retrieve the person along with orders, will spring data jpa give the result in single db call or need to extract data from two tables separately?

Person person = personRepository.findByName("person1").get();   \\for eg: consider name is unique here
List<Order> orders = orderRepository.findByPersonId(person.getId());

or any alternative in single db call?

Giving clarity to these questions is really appreciated.

Thanks for the answers in advance.



Solution 1:[1]

Have a look at cascade types. By adding a cascade type, you could save both objects with just 1 repository call.

@Entity
public class Order {
    // other fields...
    @OneToMany(mappedBy = "person", cascade = CascadeType.ALL)
    private List<Order> orders;
}

@Entity
public class Person {
    // other fields...
    @ManyToOne
    private Person person;
}

Order order = new Order();
Person person = new Person();
person.setOrders(List.of(order));
order.setPerson(person);
personRepository.save(person); // <--- since save action on person cascades, it will also save the order.

Make sure that the objects are linked to each other before saving (the 2 rows above the repository call in the example above)

Regarding fetching data If you call e.g. the personRepository and it has orders linked to it, you can either access them by configuring eager fetch (not recommended) or by wrapping your method in a Transactional annotation and access the orders programmatically instead.

@Transactional
public void doSomething() {
    Person person = personRepository.findById(1);
    List<Order> orders = person.getOrders();
}

Note that from a db perspective, in both scenarios with saving and fetching data, the same number of queries will be executed as when calling with separate repositories, but you reduce the code needed to do so and its a bit easier to work inside a transaction and only focus on the java object instead of having to call multiple repositories, especially as your db data model grows.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1