Skip to main content

Command Palette

Search for a command to run...

Adding A Repository Facade

Published
•4 min read•View as Markdown

In the evolution of BDO's, especially with my patch actions, It seemed very nice to move more logic out of the service. Such that the service fully works on BDOs and isn't aware of any DTO or DAO, more like the onion architecture. This is not a must for me, but just as an experiment, I do see some value in it. In this blog post, I attempt to make the service work without knowledge of the DAO, in the next blog post, we will put everything together and make the service work only on BDOs.

The idea is pretty simple: the facade loads the DAO and maps it to the BDO, the service will then manipulate/modify the BDO and pas it back to the facade. The facade has to convert it back to a DAO and save it. The main challenge with this approach is how to perform the same updates on the DAO. Of course, the simple solution is just to map the BDO to a new DAO object, but will this work in Hibernate, or do we have to fetch the DAO again from the database to be able to perform the updates on an existing DAO?

When I tried out this approach, I also discovered another issue, which is more connected to the way I design my BDOs. Where in the past, I had a certain command or new BDO with all the new information and I could simply perform the actions on the DAO, I now have to do these actions on the BDO, meaning that my BDO needs setters for all the data that can be modified. This feels a bit dirty, but then again, the data is allowed to be modified, and in the past, I did this directly on the DAO. By having the setters on the BDO, the object itself can perform some checks and enforce certain requirements.

My first approach to fix the unknown DAO problem was to simply create a new DAO and save that one.
From a database perspective that wouldn't be a problem, since you are just overwriting the entry, but I know that Hibernate can sometimes complain about this, as Hibernate doesn't have this newly created object in its object pool. With my first attempt however, I did not encounter this problem. I don't know if this is because I use Spring or this is just something Hibernate has evolved from.

The only remark about this is that I now need to have a setter on the id od my DAO in order to populate it. Is this a problem? Well, the id is something the database manages, and I don't feel my code should be able to set this. In the old system I could guarantee this, because I would update/modify an existing DAO and the id would not have a setter (except for the private one for Hibernate), nor would there be a constructor where you could set the id.

This results in the following code for the service and the facade respectively:

public ElectionInfo update(final ElectionInfo election) {
    final ElectionInfo currentInfo = electionFacade.getById(election.getId());
    if (!currentInfo.isEditable()) {
        throw new OperationNotAllowedException();
    }

    ElectionMapper.update(election, currentInfo);
    return electionFacade.save(currentInfo);
}
public ElectionInfo save(final ElectionInfo election) {
    final ElectionDao dao = ElectionMapper.toDao(election);
    final ElectionDao updated = repository.save(dao);
    return ElectionMapper.fromDao(updated);
}

Another approach would be to fetch the DAO from the database and copy the data from the BDO to the DAO. My concern with this is that you would be fetching the same data from the database twice, which is really ridiculous. My hope is that Hibernate would be able to prevent this by using its object pool in a smart way. I verified this in a simple case, and indeed, I can only see a single select on my database. This is more similar to my current approach but is a bit more code, as you can see below:

public ElectionInfo update(final ElectionInfo election) {
    final ElectionDao dao = Optional.ofNullable(election.getId())
        .flatMap(repository::findById)
        .orElseThrow(NotFoundException::new);
    ElectionMapper.updateDao(election, dao);

    final ElectionDao updated = repository.save(dao);
    return ElectionMapper.fromDao(updated);
}

So will this become my new approach? I like this style, and I will definitely try it out on my new project. One thing I still have to find is a better name for this 'service' as I find 'facade' not very explicit. I could use something like 'StorageService'. This separate name or layer wouldn't be technically needed and you could put it straight in the repository, but since I am using Spring, that is not an option.