Do We Really Need to Create Custom Repository, Why Don't we Autowire JpaRepository Directly

A lot of the tutorials and examples available online will create a custom repository which will extends JpaRepository. This customer repository will be used to interact with the database.

Most of the time this custome repository will have no method, for example

package org.wesome.jpa.repository;

import com.sujan.example.jpa.entity.Apple;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface AppleRepository extends JpaRepository<Apple, Long> {
}

most of the methods required are already defined in JpaRepository, So the question arises

Do We Really Need to Create Custom Repository, Why Don't we Autowire JpaRepository Directly?

and the answer is

No We Don't Need to Create Custom Repository as long as we are not creating any custom method, We can Autowire JpaRepository Directly

JpaRepository provides most of the CRUD (Create, Read, Update and Delete) methods. If applications have CRUD operations only then JpaRepository can be autowired directly.

Custome Repository is required only when we need to create some custom methods which is not available in JpaRepository.

drop database if exists AppleDb;
create database AppleDb; 
use AppleDb;
create table apple (apple_id bigint not null, apple_name varchar(255), primary key (apple_id)) engine=InnoDB;
create table hibernate_sequence (next_val bigint) engine=InnoDB;
insert into hibernate_sequence values ( 1 )
package org.wesome.jpa.controller;

import org.wesome.jpa.entity.Apple; 
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class AppleController {
    @Autowired
    private JpaRepository jpaRepository;

    @GetMapping
    Apple save() {
        Apple apple = new Apple("Macintosh");
        Apple save = jpaRepository.save(apple);
        System.out.println("save = " + save);
        return save;
    }
}
package org.wesome.jpa.entity;

import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Data
@ToString
@Entity
@NoArgsConstructor
public class Apple {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long appleId;
    private String appleName;

    public Apple(String appleName) {
        this.appleName = appleName;
    }
}
package org.wesome.jpa;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class JpaApplication {
    public static void main(String[] args) {
        SpringApplication.run(JpaApplication.class, args);
    }
}
spring.datasource.url=jdbc:mysql://localhost:3306/AppleDb
spring.datasource.username=root
spring.datasource.password=root
plugins {
    id 'org.springframework.boot' version '2.3.3.RELEASE'
    id 'io.spring.dependency-management' version '1.0.10.RELEASE'
    id 'java'
}
group = 'com.sujan'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}
repositories {
    mavenCentral()
}
dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    annotationProcessor 'org.projectlombok:lombok'
    compileOnly 'org.projectlombok:lombok'
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    runtimeOnly 'mysql:mysql-connector-java'
    testImplementation('org.springframework.boot:spring-boot-starter-test') {
        exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
    }
}
test {
    useJUnitPlatform()
}
select next_val as id_val from hibernate_sequence for update;
update hibernate_sequence set next_val= ? where next_val=?;
insert into apple (apple_name, apple_id) values (?, ?);
curl --location --request GET 'http://localhost:8080/'

If JpaRepository is used, How Spring Data JPA will map in which table entity will be saved?

Customer Repository required two parameters while defining, T and ID. T denotes the class for which repository will be configured and ID denotes the data type of primary key of the entity class.

When we don't create any Custom Repository and directly autowire the JpaRepository, Spring Data JPA identity the table name by @Table(name = "Apple") configured in the entity class.

package org.wesome.jpa.entity;

import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Data
@Entity
@Table(name = "Apple")
@ToString
@NoArgsConstructor
public class Apple {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long appleId;
    private String appleName;
}

Should we ever create a custom repository then if all the required methods are provided in JpaRepository?

It depends on the context of the application, If a small POC or learning application needs to be created, all the required methods already available in JpaRepository then autowiring the JpaRepository makes more sense since we don't need any custom methods..

If we need some custom methods for example native query, then creating a Custom Repository makes more sense.

If the application will be deployed in production or there is a high probability that some new method will be required in the future, then always create Custom Repository. If the current production code is using JpaRepository and in between a custom method is required, then there will be a lot of code change required to incorporate this, a lot of places where JpaRepository was used, needs to be updated, and this will require a throw testing. So in this case, it's always better to create a Customer Repository

 

follow us on