Repository Pattern
Tags: RepositoryDesignPattern, DomainDrivenDesign, designpattern
Published: 2020-04-18 13:02:14


<b>Repository Pattern</b> is a part of <i>Domain-Driven Design</i>, It abstract out the way to access data from the database. It mediates between the domain and data mapping layers using a Repository interface for accessing domain objects. In this article, we will understand what is a <b>Repository pattern</b>, <b>Query Object</b>, <b>Mapping Metadata</b> and how it can be implemented.

<b>Repository</b> interface exposes methods for adding, updating, deleting and finding records from the database. Repository implementation encapsulates the database connection and way to execute a query on the database.

The Repository takes the help of <b>Query Object</b> to construct the database query and map the result of the query after execution to an entity (<i>or domain object</i>) using <b>Mapping Metadata</b>.

<h2><b>Query Object</b></h2>
Query Object is an in-memory (<i>programming object</i>) representation of database query. The query object is implemented as an interpreter pattern and abstracts logic to create a database query string. Query objects de-couples the database schema and domain object as we refer to in-memory objects (<i>classes and fields</i>). This gives us the flexibility to form database queries from program objects (<i>Query Object</i>).

<h2><b>Mapping Metadata</b></h2>
Once the database query is executed by Repository, Query Object needs to know how to map a resultset row to domain object (<i>or entity</i>). This can be done by providing Mapping Metadata to the Query Object.

Mapping Metadata holds object-relational mapping details as metadata. Mapping Metadata can be provided by mean of Mapper object (<i>like in a Spring framework we use RowMapper or ResultSetMapper</i>), it can be held in a metadata file (<i>example an XML or JSON file like a Mybatis ResultMap XML tag in mapper file</i>) or can be annotated on the class field.

Let’s look into the implementation details of the Repository Pattern. We are going to implement a repository pattern simply.
<ul>
<li>Expose Repository interface with CRUD methods</li>
<li>Implement a Query Object</li>
<li>Implement a Mapper Metadata</li>
</ul>


<h2><b>Repository Interface</b></h2>
Repository interface exposes CRUD methods: Create, Retrieve(<i>Find</i>), Update, Delete.

{% gist https://gist.github.com/nileshborole/54ae0a1d776c6f77e54ec6c5b433e29c %}

<h2><b>Query Object</b></h2>
Two types of query objects: Here we are using a simple implementation of query object which will encapsulate string SQL query and query parameters.

1. <b>Query</b>: <i>SqlQuery</i> wraps the SQL database query string and parameters.
<br/>
{% gist https://gist.github.com/nileshborole/5d5fbb33145df4fc6c33a129732bef25 %}
<br/>
2. <b>FinderQuery</b>: <i>SqlFinderQuery</i> is an extension of SqlQuery and encapsulates the way to map database resultset to domain objects using RowMapper object.

{% gist https://gist.github.com/nileshborole/f082b9891f27762fb81c5b7fc5ef1237 %}

A <b>SqlRowMapper</b> is an interface to map resultset to domain objects or entities.

{% gist https://gist.github.com/nileshborole/c046ba71c1f7ce636a2c553485bb0bcd %}

<h2><b>SQL Repository Implementation</b></h2>
A <b>SqlRepositoryImpl</b> is an implementation of a <b>Repository</b> interface that encapsulates JDBC DataSource and implements <b>CRUD</b> (<i>Create, Retrieve, Update & Delete</i>)methods.

{% gist https://gist.github.com/nileshborole/955f7588f203a1c70f6056866ad0284d %}

Heres a class diagram of above code:

![Repository Pattern](https://dev-to-uploads.s3.amazonaws.com/i/pg1g2by5cvpq4ldqg1hi.png)

<h2><b>When to use Repository Pattern</b></h2>
If you are dealing with multiple entities or domain objects, and have to write many database queries then a Repository Pattern will be helpful to reduce the redundant code, reduce the amount of code needed to implement for all queries.

Repository pattern is also beneficial when connecting to multiple data sources. Repository abstract out the implementation of how to access the database, database client (<i>can be a JDBC client in case of a relational database</i>) and takes care of all data access operations. With this abstraction, you can easily switch the target database for domain objects.


<p><i>Please visit GitHub repository Persistence, which is a <a href="https://github.com/study-port/persistence">persistence framework</a> implemented using a repository pattern.</i></p>


<h4><b>References:</b>

1. https://deviq.com/repository-pattern/
2. https://martinfowler.com/eaaCatalog/repository.html
3. <a href="https://martinfowler.com/books/eaa.html">Object-Relational Metadata Mapping Patterns from Patterns of Enterprise Application Architecture</a>
4. <a href="https://en.wikipedia.org/wiki/Specification_pattern">Specification Pattern</a>