Related: Trouble Shooting


If we don't want to use Model and Finder then we typically use the repository pattern. This means we create a repository for each entity bean type and we put the "finder logic" and "persisting logic" on the repository.

Generally we will be using a DI container like Spring or Guice and our repository classes will be singleton components with constructor injection taking the EbeanServer instance (that we configure and create using ServerConfig and EbeanServerFactory).

e.g. CustomerRepository

package org.example.repository;

import io.ebean.BeanRepository;
import org.example.domain.Customer;

public class CustomerRepository extends BeanRepository<Long,Customer> {

  public CustomerRepository(EbeanServer server) {
    super(Customer.class, server);

  // ... add customer specific finders and persist logic

  public List<Customer> findByName(String nameStart) {
    return query().where()
           .istartsWith("name", nameStart)


Typically we then @Inject the repository where we want to persist or fetch beans.

e.g. CustomerService


public class OrderService {

  private final OrderRepository orderRepository;

  private final CustomerRepository customerRepository;

  private final ProductRepository productRepository;

  public OrderService(OrderRepository orderRepository,
                      CustomerRepository customerRepository,
                      ProductRepository productRepository) {

    this.orderRepository = orderRepository;
    this.customerRepository = customerRepository;
    this.productRepository = productRepository;


The potential downside to using the repository pattern vs Model and Finder is that we can sometimes see many repositories injected in some services. When we end up with many dependencies for a single service this can make constructor injection less appealing.

With Model and Finder we tend to end up with simpler / easier code and arguably it is just as easy to test and mock (using ebean-mocker).

Edit Page