Part 1: Patterns Of Enterprise Application Architecture

Mapping to Relational Databases

Part 1: Organizing Data Structure of Database

Row Data Gateway

  • Represents a single row in a database table as an object
  • Each object has methods for accessing it’s row’s data.
class Customer

this.name;

function insert();
function update();
function delete();
find(id);
findForCompany(companyID);

Table Data Gateway

  • Represent an entire table in a database.
  • Provides methods for operations on set of rows
class PersonRecordSet

function find(id);
function findWithLastName(name);
function update(id, name);
function delete(id);

Data Mapper

  • Represents a layer of code that sits between the in-memory domain objects and the database, ensuring that the two remain independent of each other.
  • Allow domain model to stay “pure” - containing only business logic while persistence concerns are centralized in mappers.
class PersonMapper

constructor(personRecordSet) {
    this.rs = personRecordSet; // depends on the gateway   
}

async rename(name)
async save(person);

// manipulate domain object; mapper figures out persistence
const mapper = new PersonMapper(new PersonRecordSet(db));
const person = await mapper.findById(7);
person.rename('Ng');
await mapper.save(person);

Takeaways

  • Avoid more than three or four joins per query, otherwise performance will suffers.
  • Defer referential integrity checking to the end of the transaction to improve performance.
  • Avoid select * to reduce unnecessary data transfer.
  • Favor static SQL over dynamic SQL.
    • Avoid string concatenation to put together SQL queries, consider parameterized query instead for safety and security.

Reference