Wednesday, 11 February 2015

Dynamic Joins for MyBatis 3: Loading Relationships on demand without the N+1 problem

At my last project at  work there was an entity, lets call it  Project, that was the center of the application. The Project had several relationships, and usally when you loaded a Project you need it with some of this relations, and furthermore, some relations of those relations.

In order to avoid  the n+1 problem, whe first started an aproach similiar to the one described in this post.

But soon the Mappers.xml started to get a mess. A real mess. Multiple resultMaps, lots of joins code in the mappers, adhoc solutions, etc....

We need another solution to be able to load an entity with just the relations we needed in the upper layer. The first solutions worked but felt kind of clumsy, with a Join<EntityName>.java for each entity, and several design problems (own relationships weren't posible, tow relations with the same entity where messy) and overall the solution was complex. Just a letter wrong and the joins woulnd't function or the result was wrong.

It did the work but I felt like it was not right. Why to write new clases for a join if all the information you need are on the Entitiy itself and its mapper? Version 2 of Dynamic Joins (DJ) was born.

What is it for?

 Lets use this model for the rest of the post.
  • An Author has a name and several Posts.
  • A Post has text and several Replies.
  • A Reply has text.
The goal of DJ its to be able to tell de model how you want an Author to be filled. You want it just as it is? Ok. Maybe you need it with all its Post loaded but don't want the Replies? Easy.  You want it all loaded? Great!
No need for any extra query for each escenario, no new functions and just one query will be executed on the DB. Also, no extra dependecies.

But how do I tell Mybatis witch relations do I want?
Just an instante of the same entity is used as a filter. Each field that is not null that represent a relationship is loaded.  For example, with the next code an Author with its Post is loaded.

Another example. An Author with its Post and each Posts with its Replies.

No need for new clases or changes. Simple as that.

How do I use it?
I'm still working in a manual and making it a library or if liked, propose a push to Mybatis git. Meanwhile i've made a github repository.

This repository contains an example project using maven with all the code and a couple of test to show its functionality. The code is release und GNU General Public License.

In the next post I will explain what are the requisites  and changes to be made (just a couple) for this to work with with any entity.

No comments:

Post a Comment