8

Normally, a Data Mapper maps data of one particular table. (Theoretically it should be communicating between Storage and a Domain Object, but its not possible in my case, so I am directly communicating with tables.)

Table1Mappper > Table1

But if that table requires data to be joined from another table, then you are expanding the scope of your Data Mapper which was only suppose to mapping from one table.

Table1Mapper > Table1 :inner-join: Table2

Wouldn't it be better if Table2 had its own mapper Table2Mapper to maps its data?

If you think Yes, then if you want to show a list of records from Table1Mapper and then later use Table2Mapper to get those data that were supposed to be joined, You are going to running a query in a loop, which is not good either.

What are you insights on this way?


Another way is to change your mapper to handle sub tables?

class Table1Mapper {
    public main_table = 'table1';
    public sub_table1 = 'table2';
}

Which I think is fine, but only until the scope of the entire mapper is dealing one particular entity in the application. For example post and post_author. But if the scope is different like post and gallery, the above will not give a ideal data mapper. To illustrate this

class PostMapper {
     public table_name = 'tbl_post';
     public gallery_table_name = 'tbl_gallery';
}

Is not correct is it? But however you would want to grab the galleries of one post in one query though, because adding an overhead of query in a loop is not a good solution performance.

What do you think is the right way to solve this in DataMapper Pattern / or any other pattern if it has better way of handling such cases?

5

By Data Mapper you mean one described by Martin Fowler, right? It is one of Data Source Architectural Patterns patterns. Others are:

Data Mapper differs from other patterns with regard to relationship between objects and tables. Both Data Gateway patterns and Active Record pattern assume almost one to one mapping from tables to objects.

Let's take a look at an example:

table BANK_ACCOUNT
   ID

table BANK_ACCOUNT_BALANCE
   ID
   BANK_ACCOUNT_ID
   BALANCE_AMOUNT
   DATE

Domain objects are then:

class BankAccount {
    long id;
}

class BankAccountBalance {
    long id;
    long bankAccountId;
    Decimal balanceAmount;
    Date date;
}

As you see one to one mapping between classes and tables. There are also two different Table/Row Data Gateways or Active Records - one for each table.

In contrast, Data Mapper allows for indirection:

A layer of Mappers (473) that moves data between objects and a database while keeping them independent of each other and the mapper itself.

So when you are using Data Mapper your objects can differ from database tables. You are free to introduce aggregation, joins with other tables, perform arithmetical operations, introduce inheritance hierarchies. So answering your question - it is perfectly fine to join two tables in Data Mapper as long as the result object is valid domain object.

In our example we could have:

class BankAccount {
    long id;
    Decimal latestBalance;
    Date latestBalanceDate;
}

as domain object returned by single Data Mapper based on JOIN and aggregation.

Therefore, Data Mapper is perfect for representing non-trivial domain model. If your domain model is rather simple you might consider using Active Record pattern or Data Gateways.

Need for JOINs Data Mapper might sometimes (but not must) indicate that domain class is too complex. Please check Single Responsibility Principle, Interface Segregation Principle.

In Domain-Driven Design domain classes (i.e. returned by Data Mapper) take form of entities or value objects. DDD book pretty well describes what should an entity comprise of. You might want to check this out.

Additionally DDD defines Aggregates (pretty well described here). They are often loaded together. Joining two tables might suggest that there are two entities in single aggregate.

1
  • Thanks. My only concern was that different tables although related to one another could have their individual Mapper maintaining them. If another mapper does a part of this because the data is related, then the logic of maintaining or abstracting the data of the related is separated among two mappers. This is what feels like "This could be done in better way" kinda feeling inside.
    – Starx
    Sep 17 '15 at 8:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.