JPA – the database link

The Java Persistence API (JPA) is the link to the database (MySQL for our quote application we created in chapter 1). Its goal is to enable an application to map the database model to Java objects. The gain is that we can use the database as any object.

For instance, consider the following table, which matches our quote representation in the database:

The preceding table can be converted into the following object in Java, thanks to JPA annotations:

While the tables are flat, mapping them in JPA is pretty straightforward, but the more the model complexity will increase, the more you will realize the two opposed worlds: building a great Java model can lead to an awful database model or the opposite. Why? Because both don't share exactly the same philosophy and can lead to some anti-patterns.

For instance, in our model, we linked our Quote to Customer mapping. Since a customer can have multiple quotes (and the opposite as well), we used a @ManyToMany relationship. If you check the database generated by JPA, you will be surprised to see one table that is not modelized:

The QUOTE_CUSTOMER table model is pretty simple if you open it:

As you can see, it just makes a link between the QUOTE and CUSTOMER tables. This is what we would manually do on the database side, except that we would modelize this table (it wouldn't be implicit) and potentially add some attributes owned by the relationship (something we can't do with our current Java model).

Of course, you can always modelize this join table and link it to  Quote and  Customer with  @ManyToOne relationships if you need more flexibility or want to be closer to the database model.

This example is interesting at two levels:

  • What will the JPA provider do to fetch the quotes of a customer, since there is this join table in the middle?
  • The model is symmetric: a customer can get the quotes he can access, and we can access the allowed customers from a quote. In Java, it will just be translated by quote.getCustomers() and customer.getQuotes(). Are both doing the same thing? Are they similar in terms of performance? In Java, they really look the same, right?

To dig into the role of the provider, we must start by checking how by using some object-related code and query language the provider can actually make it work on the database-side, which uses a different paradigm. To do so, we will first investigate how our Java code is converted to native SQL and, then, check how the modeling can impact the performance.