MergeMitra (α-version) vs Greptile: Automated Code Reviews

Published onAuthorSujit Senapati

Repository

Both tools were evaluated on the same repository — a realistic, multi-layered backend application.

The project includes:

  • Spring Boot backend architecture

  • Spring Data JPA (Hibernate)

  • Spring Security authentication

  • Repository / Service / Controller layers

  • Admin and user functionality

  • MySQL database

Because the repository contains multiple layers and security configuration, it provided a realistic scenario for testing AI code review tools.

  • Spring Boot 2.6
  • Spring Data JPA
  • Spring Security
  • MySQL
  • JSP / JSTL
  • Spring Boot Actuator
  • OpenAPI / Swagger
  • Maven

ORIGINAL REPOSITORY:

REFACTORED REPOSITORY:

Head-to-Head Comparison

CategoryGreptileMergeMitraWinner
Depth of AnalysisIndividual issues, incorrect JPQL queries, unused importsArchitecture, security config, transactions & persistence layersšŸ†Ā MergeMitra
Security ReviewPlaintext passwords, missing security headersPassword logging, double BCrypt encoding, credential exposure in propertiesšŸ†Ā MergeMitra
Architecture ReviewMostly line-level code issuesDetects controllers performing DB operations directlyšŸ†Ā MergeMitra
Testing SuggestionsLimited testing insightsMockMvc, DAO integration tests, security testsšŸ†Ā MergeMitra
Code QualityMinor suggestionsMaintainability improvements and best practicesšŸ†Ā MergeMitra

PR Review Scorecard

After seeing MergeMitra's PR scorecard, I went on to address the issues, raised a PR and found the scores improved on all four dimensions.

Fig 1: MergeMitra PR quality score (Before refactoring)

PR Scorecard before refactoring

MergeMitra identified 69 issues. After refactoring the code and resolving these issues, the updated scorecard is shown below.

Fig 2: MergeMitra PR quality score (After refactoring)

PR Scorecard after refactoring

Issues highlighted by MergeMitra

Code Correctness & Design Quality

  1. HibernateConfiguration.java:69 – transactionManager.setSessionFactory(sessionFactory().getObject()) may return null during initialization.

  2. SecurityConfiguration.java:100 – UserDetailsService re-encodes password causing authentication failure.

  3. SecurityConfiguration.java:96 – user.getRole().equals("ROLE_ADMIN") may cause NPE.

  4. SecurityConfiguration.java:32 – Deprecated antMatcher/antMatchers used with new DSL.

  5. SecurityConfiguration.java:53 – CSRF protection disabled with form login.

  6. cartDao.java:29 – HQL uses table name (CART) instead of entity name.

  7. cartProductDao.java:30 – Same entity-name issue in HQL.

  8. categoryDao.java:32 – Same entity-name issue in HQL.

  9. productDao.java:25 – Same entity-name issue in HQL.

  10. userDao.java:29 – Same entity-name issue in HQL.

  11. cartProductDao.java:41 – IN (:product_ids) fails when list is empty.

  12. cartProductDao.java:36 – Native query may return DB-specific numeric types (e.g., BigInteger).

  13. categoryDao.java:39 – session.load() used instead of session.get().

  14. productDao.java:47 – Same session.load() issue.

  15. categoryDao.java:50 – Possible NPE in updateCategory.

  16. productDao.java:40 – Session.update(String.valueOf(Product.class)) invalid entity name.

  17. productDao.java:39 – getCurrentSession() used without @Transactional.

  18. userDao.java:50 – Logging user.getPassword().

  19. userDao.java:51 – Plaintext password comparison.

  20. userDao.java:56 – Generic Exception catch hides real errors.

  21. userDao.java:73 – HQL uses User instead of CUSTOMER entity name.

  22. CartProductRepository.java:7 – JpaRepository used without JPA configuration.

  23. Product.java:24 – Incorrect @OneToOne mapping for category (should likely be @ManyToOne).

  24. productService.java:28 – updateProduct does not verify entity existence.

  25. userService.java:22 – Password stored without hashing.

  26. UserController.java:95 – Similar plaintext password handling.

  27. userService.java:25 – Generic RuntimeException hides real DB error.

  28. AdminController.java:133 – product.setId(categoryId) overwrites product primary key.

  29. AdminController.java:157 – Product update endpoint not implemented.

  30. AdminController.java:90 – State-changing operations exposed via GET requests.

  31. AdminController.java:231 – Password updated as plaintext via SQL.

  32. UserController.java:127 – Password exposed in UI model.

Test Quality & Coverage

  1. SecurityConfiguration.java:26 – No tests for security filter chains and access rules.

  2. cartDao.java:21 – DAO queries lack integration tests.

  3. cartProductDao.java:34 – Same DAO query test gap.

  4. categoryDao.java:35 – Same DAO query test gap.

  5. productDao.java:23 – Same DAO query test gap.

  6. userDao.java:44 – No tests for authentication DAO methods.

  7. userService.java:22 – No tests for password hashing logic.

  8. cartService.java:16 – Service methods lack tests.

  9. categoryService.java:18 – Service methods lack tests.

  10. productService.java:28 – Service methods lack tests.

  11. AdminController.java:45 – No controller tests for admin endpoints.

  12. UserController.java:42 – No controller tests for user endpoints.

Code Readability & Maintainability

  1. HibernateConfiguration.java:18 – Non-constant uppercase field names (DRIVER, URL).

  2. SecurityConfiguration.java:20 – Same naming convention issue.

  3. HibernateConfiguration.java:44 – DriverManagerDataSource used instead of pooled datasource.

  4. cartDao.java:13 – DAO class naming convention violation.

  5. cartProductDao.java:14 – Same naming issue.

  6. categoryDao.java:14 – Same naming issue.

  7. productDao.java:15 – Same naming issue.

  8. userDao.java:19 – Same naming issue.

  9. cartService.java:12 – Service naming convention issue.

  10. categoryService.java:14 – Service naming convention issue.

  11. productService.java:12 – Service naming convention issue.

  12. userService.java:14 – Service naming convention issue.

  13. cartDao.java:32 – Commented-out dead code.

  14. userDao.java:40 – Commented-out dead code.

  15. Cart.java:19 – Commented-out code.

  16. cartService.java:20 – Commented-out code.

  17. UserController.java:175 – Commented-out code.

  18. userDao.java:36 – System.out.println used instead of logging.

  19. AdminController.java:80 – Same logging issue.

  20. UserController.java:102 – Same logging issue.

  21. AdminController.java:186 – Controller contains raw JDBC logic.

  22. AdminController.java:192 – Hardcoded DB credentials in controller.

  23. AdminController.java:210 – Password exposed to UI model.

  24. AdminController.java:192 – JDBC resources not closed.

  25. UserController.java:96 – Controller binds HTTP data directly to JPA entity.

Issues highlighted by Greptile

userDao.java – Wrong HQL entity name (from User instead of from CUSTOMER) causing authentication failure.

AdminController.java (lines 191–219) – Hardcoded DB credentials and unclosed JDBC connection.

AdminController.java (lines 233–236) – Password stored as plaintext instead of BCrypt hash.

AdminController.java – product.setId(categoryId) incorrectly sets product ID to category ID.

AdminController.java (lines 157–163) – Product update endpoint is a no-op (update call commented out).

UserController.java – Hashed password exposed to the view (model.addAttribute("password", user.getPassword())).

categoryService.java – Unused ByteBuddy import.

userDao.java – Unused MIDI import (Soundbank).

UserController.java (lines 18–28) – Duplicate and unused cartService import.

SecurityConfiguration.java – CSRF protection disabled in both filter chains.

My Experience with MergeMitra

"Using MergeMitra felt like having an expert Java lead reviewing my PR, not a linter checking surface-level issues."

Instead of pointing out syntax-level issues, it identified deeper systemic problems that would have taken hours to find manually.

šŸ”’ Security Vulnerabilities

Detected password logging, double BCrypt encoding, and hardcoded credentials leaking into properties files.

šŸ› Architecture Anti-patterns

Controllers were directly performing JDBC operations — a clear separation-of-concerns violation.

šŸ“Š Transaction Boundaries

Missing @Transactional annotations causing unpredictable DB behavior.

šŸ”— Entity Relationships

Improper JPA mappings leading to N+1 query problems and data integrity risks.

How It Saved Reviewer Time

Manual code reviews on multi-layer repositories can consume hours. MergeMitra accelerated this process significantly.

Instant critical issue detection

Surfaced incorrect entity mappings, security misconfigs, and transaction issues in one pass — while the context was still fresh.

Actionable, location-specific suggestions

Each issue included a clear problem description, exact file location, and a suggested code fix.

No ambiguity, no back-and-forth.

Reduced PR review overhead

Catching issues early compressed time spent in pull request reviews, debugging sessions, and security audits.

Final Thoughts

AI-assisted code reviews are becoming an essential part of modern development workflows. While Greptile offers useful lint-style analysis at the line level, my evaluation showed that MergeMitra delivers meaningfully deeper insights — covering architecture, security, and system design holistically.

For teams building production-grade applications, that level of review can be the difference between shipping reliable software and accumulating silent tech debt.

If you're building with Spring Boot and care about secure, maintainable backend architecture — both tools are worth exploring. But for depth and architectural context, MergeMitra goes well ahead.