DEV Community

loading...

Spring Data JPA | getOne() vs findById() ! Farkları nedir?

Burak Aykan ÜRER
Software Developer | Backend Developer @BulutMD.com Java | Spring Boot | Hibernate | MySQL | Microservices | React Love learning, coding and coffee.
Originally published at blog.burakaykan.me on ・3 min read

Spring Data JPA | getOne() vs findById() ! Farkları nedir?

Spring Data JPA'da getOne() metodu da findById() metodu da bir objeyi getirmek için kullanılabilir. Ancak bu iki metodun çalışma prensibi farklıdır. Bu yazıda bu farklara değineceğim.


- getOne()

getOne() metodu verilen id'ye ait objenin referansını döner. Bu metod içeride EntityManager.getReference() metodunu çağırır. Dökümanda belirtildiği gibi bu metod her zaman database'e gitmeden (lazy fetch) bir proxy döner. İstenen entity'nin database'de bulunmaması durumunda EntityNotFoundException fırlatır.

- findById()

Bu metod ise her çağırıldığında gerçekten database'e gider ve objeyi oradan getirir. Bu EAGER yüklenen işlemdir bu sebeple eğer getirmeye çalıştığımız obje DB'de yoksa null dönecektir.


Hangisini seçmeliyiz ?

Bu iki metodun arasındaki temel fark performans ile ilgili, Lazy Load olan getOne() JVM'den database'e gitmediği için performans olarak findById()'den daha iyidir.

İki metodu da kullanmak için uygun durumlar var. Örneğin objeyi getirip başka bir obje ile ilişki kurmasını sağlamak istediğimizde (OneToOne ya da ManyToOne). Ancak örneğin çağırdığımız objenin içerisinde bulunan başka bir objeye erişmeye çalıştığımızda hata alacağız bu gibi durumlarda findById() metodunu kullanmak daha iyi olacaktır.

findById kullandığımızda

    @PostMapping("/findById/{id}")
    public void findByIdCreate(@PathVariable Long id) {
        Employee employee = new Employee();
        employee.setName("MyEmployee");
        Instant start = Instant.now();
        Department department = departmentRepository.findById(id).get();
        Instant end = Instant.now();
        System.out.println(Duration.between(start, end));
        employee.setDepartment(department);
        employeeRepository.save(employee);
    }

insert yapmadan önce select sorgusu ile Departmanı getiriyoruz arkasından insert metodu 0.004S'de çalışıyor.

Hibernate: select department0_.id as id1_0_0_, department0_.name as name2_0_0_ from Department department0_ where department0_.id=?
PT0.004S
Hibernate: insert into Employee (department_id, name) values (?, ?)

getOne kullandığımızda

    @PostMapping("/getOne/{id}")
    public void getOneCreate(@PathVariable Long id) {
        Employee employee = new Employee();
        employee.setName("MyEmployee");
        Instant start = Instant.now();
        Department department = departmentRepository.getOne(id);
        Instant end = Instant.now();
        System.out.println(Duration.between(start, end));
        employee.setDepartment(department);
        employeeRepository.save(employee);
    }

ise Departman'ın referansını getirdiği için yani aslında database'e gitmediğimiz için işlem çok daha hızlı gerçekleşir.

PT0.002S
Hibernate: insert into Employee (department_id, name) values (?, ?)
getOne() findById()
Lazy Load ile hedefin referansını getirir Verilen id'yi gerçekten getirir (referans değil)
Objenin propert'ilerine erişmek gerekmediğinde oldukça kullanışlı Obje tamamen getirildiği için tüm özelliklerine erişilebilir
Objeye erişmek gerektiğinde obje DB'de yoksa EntityNotFoundException hatası fırlatır Eğer obje DB'de kayıtlı değilse null döner
Daha iyi performans İlave bir DB sorgusu gereklidir

Kaynak - Github Proje

Discussion (0)