Guide to EzyDatabaseRepository, EzyJpaRepository, and Transactions

Updated at 1782264852000
In most cases, users should define repositories by extending EzyDatabaseRepository. This is the default and recommended approach for common CRUD operations, method-name queries, @EzyQuery, pagination, count, delete, and simple update operations.
@EzyRepository
public interface UserRepository extends EzyDatabaseRepository<Long, User> {

    User findByEmail(String email);

    List<User> findByStatus(String status, EzyNext next);

    long countByStatus(String status);

    int deleteByStatus(String status);

    @EzyQuery("update User e set e.status = ?1 where e.id = ?0")
    int updateStatus(long id, String status);
}
With this approach, EzyData automatically generates the repository implementation. Methods such as findBy..., countBy..., deleteBy..., or methods annotated with @EzyQuery are converted into corresponding JPA queries.

When to Use EzyDatabaseRepository

Use EzyDatabaseRepository when:
  • the repository only needs common CRUD operations,
  • the query can be expressed by method name, such as findByEmail, countByStatus, or deleteById,
  • the query can be written directly with @EzyQuery,
  • one transaction per write query is enough,
  • you do not need to control EntityManager manually,
  • you do not need to group multiple JPA operations into one manual transaction.
This should be the preferred approach because the code is shorter, easier to read, and consistent with EzyData’s auto-implementation mechanism.

Default Transaction Behavior

When using an auto-implemented repository from EzyDatabaseRepository, EzyData handles transactions for write queries.
Methods starting with update... and delete... are executed inside a transaction:
@EzyQuery("update User e set e.status = ?1 where e.id = ?0")
int updateStatus(long id, String status);

int deleteByEmail(String email);
Internally, the flow is:
transaction.begin();

try {
    query.executeUpdate();
    transaction.commit();
} catch (Exception e) {
    transaction.rollback();
    throw e;
}
Read methods such as findBy..., countBy..., and fetch... only create a query, fetch data, and close the EntityManager; they do not start a write transaction.

When to Use EzyJpaRepository

In some cases, users may want to implement transactions themselves or control the EntityManager directly. In that case, create a repository class and extend EzyJpaRepository.
This approach is suitable when:
  • you need to group multiple JPA operations into the same transaction,
  • you need to execute multiple queries before committing,
  • you need to decide when to flush, commit, or rollback,
  • you need to use specific EntityManager APIs,
  • the business logic is too complex for @EzyQuery,
  • the transaction must wrap multiple business steps inside one repository method.
Example:
@EzyRepository
public class UserRepository extends EzyJpaRepository<Long, User> {

    public void changeEmailAndStatus(
        long userId,
        String email,
        String status
    ) {
        EntityManager entityManager = databaseContext.createEntityManager();
        EntityTransaction transaction = entityManager.getTransaction();

        try {
            transaction.begin();

            User user = entityManager.find(User.class, userId);
            user.setEmail(email);
            user.setStatus(status);

            entityManager.merge(user);

            transaction.commit();
        } catch (Exception e) {
            transaction.rollback();
            throw e;
        } finally {
            entityManager.close();
        }
    }
}
Then register the repository class:
EzyDatabaseContext context = new EzyJpaDatabaseContextBuilder()
    .entityManagerFactory(entityManagerFactory)
    .repositoryClass(UserRepository.class)
    .build();

Recommendation

By default, use EzyDatabaseRepository so EzyData can automatically generate the repository implementation and handle transactions for each write query.
Only use EzyJpaRepository when you truly need to manage transactions yourself or work directly with EntityManager. It gives you more flexibility, but you are responsible for calling begin, commit, rollback, and close correctly.

Table Of Contents