Course contentsShow
← Node.js
Lesson 825 of 1,9808. Data Persistence and ORM IntegrationFree lesson

Encapsulating Data Access Logic

You will adopt the Repository pattern to decouple your application logic from your ORM.

In this lesson, you will learn how to isolate your database operations from your business logic using the Repository Pattern.

Why Encapsulate?

So far, you’ve likely been calling your ORM methods (like User.findAll() or db.query()) directly inside your service functions or controllers. While this is fast, it creates "leaky abstractions." If you ever decide to switch ORMs or modify how your data is structured, you would have to hunt down and update every single file that touches the database.

The Repository pattern acts as a middleman (a "mediator") between your domain logic and your data source.

Implementing a Repository

Instead of letting your controller talk directly to the database, you create a repository class that manages the persistence logic. Here is a simple example:

// UserRepository.js
class UserRepository {
  constructor(model) {
    this.model = model;
  }

  async findActiveUsers() {
    // All the complex ORM-specific logic lives here
    return await this.model.findAll({ where: { status: 'active' } });
  }

  async create(userData) {
    return await this.model.create(userData);
  }
}

// In your controller/service
const userRepo = new UserRepository(User);
const activeUsers = await userRepo.findActiveUsers();

The Benefits

By using this approach, your service layer no longer needs to know that you are using an ORM or even a database at all.

  1. Decoupling: Your business logic focuses on "what" needs to be done (e.g., "get active users"), while the repository handles "how" it's done (e.g., the specific ORM syntax).
  2. Simplified Testing: You can easily swap your actual repository for a "mock" repository during unit testing without needing a real database connection.
  3. Consistency: If you need to add a global filter—like ensuring soft-deleted records are always excluded—you only have to change it in the repository method, not in twenty different controllers.

By centralizing these calls, you turn your database layer into a robust, predictable API that your application consumes, rather than a mess of queries scattered throughout your codebase.

Key Takeaway: The Repository pattern creates a clean boundary that shields your business logic from database changes, making your code easier to maintain and test.