Skip to content

Querying Data with Spring Boot

InsyaAllah pada bagian catatan ini akan membahas topik-topik, diantaranya;

Folder Contoh

Kode dapat dilihat pada module bagian_3_1

Adding Spring Data to an Existing Spring Boot Application

Spring Data adalah tiket untuk management data yang multiguna.

Using Spring Data to Easily Manage Data

Spring data memiliki penedekatan yang untuk mempermudah akses data. Spring data tidak menggunakan lowest common denominator. Ini adalah taktiknya, dimana API tunggal yang terdefinisi pada sebuah interface dan implementasinya menawarkan untuk setiap data store.

Setiap data store memimiliki berbaga cara untuk mengkases data. Pertama, hampir semua modul Spring Data memiliki sebauh template yang memberikan kita kemudahan untuk mengakses data fitur dari data penyimpanan. Beberapa templatenya diantaranya;

  • Redis Template
  • Cassandra Template
  • Mongo Template
  • Couchbase Template

Setiap Modul Spring Data memiiki core templatenya masing-masing. Mereka semua memiliki siklus hidup yang mirip, seperti bagaimana mereka menangani manajemen sumberdaya. Setiap template memiliki berbagai macam fungsi, beberapanya berdasarkan pada common data access paradigm dan lainya berdasarkan pada data store's native features.

Karena kita dapat melakukan hampir apapun dengan template data store, ada cara yang lebih mudah untuk mengakses data. Banyak modul Spring Data termasuk didalamya repository support, yang membuat Spring Data mempu membuat query, updates dan deletes, berdasarkan tipe domain aslinya.

Ada kesamaan yang mendasari semua pendekatan tersebut. Membuat statement, apakah itu select untuk Redis, MongoDB atau Cassandar, tidak hanya merepotkan namun juga berta saat memaintai statement tersebut. Mengingat sebagian besar kueri hanya menyalin nilai struktural yang dipetakan ke jenis dan bidang domain nama, Spring Data memanfaatkan informasi domain untuk membantu pengembang menulis query.

DTOs, entities, and POJOs, oh my!

Sebelum menulis kode, kita harus memahamin paradigma dasarnya terlebih dahulu. Data Transfer Object (DTOs), entities dan Plain Old Java Object (POJO).

  • DTO: A class whose purpose is to transfer data, usually from server to client (or vice versa)
  • Entity: A class whose purpose is to store/retrieve data to/from a data store
  • POJO: A class that doesn’t extend any framework code nor has any sort of restrictions baked into it

Entities

Ketika kita menulis kode untuk meng-query data dari sebuah database, data hasil query tersebut akan berkahir, tersimpan pada sebuah class yang disebut dengan entity. Setiap class yang dilibatkan untuk menyimpan dan mengambil data hasil query melalaui JPA harus diberi anotasi dengan @Entity.

Code

@Entity
class VideoEntity {
    private @Id @GeneratedValue Long id;
    private String name;
    private String description;

    protected VideoEntity() {
        this(null, null);
    }

    VideoEntity(String name, String description) {
        this.id = null;
        this.description = description;
        this.name = name;
    }
    // getters and setters
}

Penjelasan kode diatas;

  • @Entity adalah anotasi dari JPA untuk menandakan bahwa ini adalah tipe JPA-managed.
  • @Id adalah anotasi dari JPA yang menandakan primary key
  • @GeneratedValue anotasi dari JPA untuk membuat key number untuk JPA provider.
  • JPA membutuhkan construtor yang tidak menerima argumen.
  • Kita juga memiliki sebuah constructor dimana filed id yang tidak kita sediakan this.id=null, artinya sebauh construtor yang dibuat untuk membuat entries baru pada database. Jadi, ketika id bernilai null, maka JPA akan tahu kita ingin membuat sebuah data baru. karena nantinya ID akan di generate.

Data Transfer Objects

DTOs digunakan pada lapisan web application. Class ini bertugas khusus pada data dan memastikan data tersebut dalam bentuk yang sesuai, apakah itu HTML atau JSON. *Jackson8, adalah JSON serialization/deserialization library bawaan Spring Boot yang memiliki berbagai macam anotasi untuk kostumisasi JSON rendering.

Mengapa kita butuh DTO dan entities. Karena class lebih mudah digunakan dan diupdate jika class tersebut difokuskan untuk melalukan tugas tunggal. Konsep ini disebut dengan single-responbility principle (SRP).

Sebuah class yang bertugas untuk melakukan transfer data (DTO) dan menerima serta menyimpan data (entities) akan sulit dimaintain dan dikelola. Sulit membuat class untuk memaintai tugas pada web layer dan persistance layer.

Creating Spring Data Repository

Sebuah repository mengumpulkans semua opererasi data untuk tipe domain tertentu pada satu tempat. Aplikasi berkomunikasi dengan repository menggunakan bahasa domain (domain speak), dan repository selanjutnya berbicara dengan data store menggunakan bahasa query.

Application âž¡ repository âž¡ data store

Maka sekarang kita buat Data Repository dengan membuat interface dengan nama VideoRepository.java

Code

public interface VideoRepository extends JpaRepository<VideoEntity, Long > {
    // Saat ini belum ada isinya
}

Penjelkasan kode diatas sebagai berikut;

  • Interface tersebut extends class #java JpaRepository dengan dua tipe generic parameter, VideoEntyty dan Long. Sebagai domain type dan primary key type.
  • JpaRepostiroy interface, mengandung kumpulan operasi CRUD (Create Repalce Update & Delete).

Spring data dikode untuk mencari semua instace dari Repository dan apply semua query derivation. Artinya, semua interface yang kita buat dan menurunkan class Repository atau superclass diatasnya akan diambil oleh Spring boot component scanning dan secara otomatis akan terdaftar untuk kita.

JpaRepository juga berisi kumpulan cara untuk mengambil data, seperti dibawah ini;

  • findAll(), findAll(Example<S>), findAll(Example<S>, Sort), findAll(Sort), findAllById(Iterable<ID>), findById(ID), findAll(Pageable), findAll(Example<S>,Pageable), findBy(Example<S>), findBy(Example<S>, Pageable), findBy(Example<S>, Sort), findOne(Example<S>).
  • deleteById(ID), deleteAll(Iterable<T>), deleteAllById(Iterable<ID>), deleteAllByIdInBatch(Iterable<ID>), deleteAllInBatch().
  • save(S), saveAll(Iterable<S>), saveAllAndFlush(Iterable<S>), saveAndFlush(S)
  • count(), count(Example<S>), existsById(ID)

Semuanya tidak ditemukan langsung pada class JpaRepository. Beberapa berada pada hierarki Spring Data repository interface, termasuk ListPaginAndSortingRepository, LisCrudRepository dan QueryByExampleExecutor. Contohnya adalah dibawah ini, interface dari CrudRepository

Code

public interface CrudRepository<T, ID> extends Repository<T, ID> {
    <S extends T> S save(S entity);

    <S extends T> Iterable<S> saveAll(Iterable<S> entities);

    Optional<T> findById(ID id);

    boolean existsById(ID id);

    Iterable<T> findAll();

    Iterable<T> findAllById(Iterable<ID> ids);

    long count();

    void deleteById(ID id);

    void delete(T entity);

    void deleteAllById(Iterable<? extends ID> ids);

    void deleteAll(Iterable<? extends T> entities);

    void deleteAll();
}

Generic type diatas penjelasannya sebagai berikut;

  • ID: Tipe generik dari primary key-nya repository
  • T: Tipe generik dari domain type
  • S: Tipe generik subtype yang menurunkan (extends) T.
  • Iterable: An iterable type that does not require all its elements to be fully realized in memory
  • Example: An object used to serve Query By Example

Operasi diatas sangatlah banyak yang dapat kita gunakan, namun kekurangnnya adalah, tidak bisa digunakan untuk query yang lebih spesifik. InsyaAllah pada catatan ini kita akan membuat query yang lebih detail secara manual menggunakan JPA.

Using Costume Finder

Untuk memmbuat costume finder, kita akan menambahkan beberapa baris kode pada file VideoRepository.java. Katakan kita ingin mengambil data berdasarkan nama dari video yang kita cara.

Code

public interface VideoRepository extends JpaRepository<VideoEntity, Long > {

    List<VideoEntity> findByName (String name);
}
  • findByName(String name); method disebut dengan costume finder. Kita tidak perlu membuat implementasi dari fungsi ini, karena SpringBoot akan melakukannya untuk kita.
  • List<VideoEntitiy> adalah nilai kembalian dari method ini.

Interface method ini adalah yang kita hanya kerjaan untuk menulis sebuah query. Dibelakang, Sprint adata akan mem-parse method name tersebut. Semua repository method yang diawali dengan findBy akan dianggap sebagai query. Selanjutnya akandianggap sebagai field, contoh diatas adala Name. Kita juga dapat menambahkan opsional kualifikasi seperti Contains atau IgnoreCase.

Kode method interface diatas akan diterjemahkan menjadi

Code

select * from video where name = ?

Nama kolom video didapatkan dari nama dari method Entitiy atau kita dapat menetapkannya dengan anotasi @Table(name="table_name")

Selain auto translate dari method interface, penggunaan Repository ini membuat kita terhindar dari SQLInjection dan secara otomatis akan mengkonversi hasil query kedalam objek domainnya, kasusu ini kedalam VideoEntitiy

Diatas itu semua, karena kita menggunakan JPA, kita tidak perlu memikirkan dialek yang berbeda pada setiap database. Apakah kita berbicara dengan MySQL, PostgreSQL atau MSSQL dan lainnya, JPA akan menangani itu semua untuk kita.

Selain Contains dan IgnoreCase ada beberapa opsional lainnya yang dapat kita gunakan untuk costume finder dalam mengambil data, diantaranya;

  • And dan Or dapat digunakan untuk menggabungkan multiple property expressions. Kita juga dapat menggunakan Between, LessThan, and GreaterThan
  • You can apply IsStartingWith, StartingWith, StartsWith, IsEndingWith, EndingWith, EndsWith, IsContaining, Containing, Like, IsNotContaining, NotContaining, and NotContains
  • You can apply IgnoreCase against a single field, or if you want to apply it to all properties, use AllIgnoreCase at the end
  • You can apply OrderBy with Asc or Desc against a field when you know the ordering in advance

Costume finder juga dapat digunakan untuk relationships. Contohnyam, jika repository domain typenya adalah Person dan memiliki Address filed dengan ZipCode. Kita dapat menulis costume finder findByAddressZipCode(ZipCode zipCode). Itu akan membuat join find pada query.

Sekarang mari kita tambahkan html form pada index.mustache yang sudah kita buat sebelumnya

Code

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/multi-field-search" method="post">
    <table>
        <tr>
            <td><label for="name">Name:</label></td>
            <td><input type="text" name="name"></td>
        </tr>
        <tr>
            <td>
                <label for="description">Description:</label>
            </td>
            <td>
                <input type="text" name="description">
            </td>
        </tr>
    </table>
    <button type="submit">Search</button>
</form>
<ul>
    {{#videos}}
        <li>{{name}} {{description}}</li>
    {{/videos}}
</ul>
</body>
</html>

Penjelasan kode diatas sebagai berikut;

  • attribute action pada tag <form/> menandakan target URL dengan method HTTP adalah POST
  • Kita membuat tag <input/> sebagai wadah input dari user yang dikirim nantinya
  • Tag <button/> yang akan men-trigger pengiriman data tersebut.

Untuk menanganin data yang diterima, kita harus membuat method pada controller class serta membuat datatype untuk memparsing nilai tersebut.

Code

record VideoSearch(String name, String description) {}

Code

...// Cutted
@PostMapping("/multi-field-search")
public String search(@ModelAttribute VideoSearch search, Model model){
    System.out.println(search.name());

    List<VideoEntity> searchResult = videoService.search(search);
    System.out.println(searchResult.size());
    model.addAttribute("videos", searchResult);
    return "index";
}
...// Cutted

selanjutnya mari kita buat sebuah service sebagai pehubung antara repository class dengan controller class.

Code

@Service
public class VideoService extends VideoEntity{
    @Autowired
    VideoRepository repository;

//    public VideoService(VideoRepository repository){}

    public List<VideoEntity> search(VideoSearch videoSearch){

        if (StringUtils.hasText(videoSearch.name()) && StringUtils.hasText(videoSearch.description())){
            return repository.findByNameContainsOrDescriptionContainsAllIgnoreCase(videoSearch.name(), videoSearch.description());
        }

        if (StringUtils.hasText(videoSearch.name())){
            return repository.findByNameContainsIgnoreCase(videoSearch.name());
        }

        if (StringUtils.hasText(videoSearch.description())){
            return repository.findByDescriptionContainsIgnoreCase(videoSearch.description());
        }
//        return repository.findAll();
        return Collections.emptyList();
    }

    public List<VideoEntity> addVideo (VideoSearch videoSearch){
        repository.save(new VideoEntity(videoSearch.name(),videoSearch.description()));
        return repository.findAll();
    }
}

Setelah mengupdate service, mari kita menambahkan repository class untuk membuat costume finder

Code

public interface VideoRepository extends JpaRepository<VideoEntity, Long> {
    List<VideoEntity> findByNameContainsOrDescriptionContainsAllIgnoreCase(String partialName, String partialDescription);

    List<VideoEntity> findByNameContainsIgnoreCase(String partialName);

    List<VideoEntity> findByDescriptionContainsIgnoreCase(String partialDescription);
}

Jalankan SpringBoot lalu buka localhost:8080/multi-field-search. Masukan keyword yang ingin dicari, maka insyaAllah akan muncul seperti dibawah ini

Hasil

Result JPA

Sorting

Ada beberapa cara untuk menyortir data, salah satunya adalah menggunakan klausa orderBy pada repository class seperti dibawah ini.

Code

public interface VideoRepository extends JpaRepository<VideoEntity, Long> {
    List<VideoEntity> findByNameContainsOrDescriptionContainsAllIgnoreCaseOrderByNameAsc(String partialName, String partialDescription);

    List<VideoEntity> findByNameContainsIgnoreCaseOrderByNameAsc(String partialName);

    List<VideoEntity> findByDescriptionContainsIgnoreCaseOrderByNameAsc(String partialDescription);

}

Cara diatas menggunakan OrderBy method. Kita juga dapat menggunakan Sort parameter pada method tersebut.

Pertama Membuat method para repository class menerima parameter Sort

Code

public interface VideoRepository extends JpaRepository<VideoEntity, Long> {

    List<VideoEntity> findByNameContainsOrDescriptionContainsAllIgnoreCase(String partialName, String partialDescription, Sort sort);

    List<VideoEntity> findByNameContainsIgnoreCase(String partialName);

    List<VideoEntity> findByDescriptionContainsIgnoreCase(String partialDescription);
}

Kedua Pada service class, buat instance sort dan berikan field tersebut pada parameter method findByNameContainsOrDescriptionContainsAllIgnoreCase().

Code

// ... cutted
public List<VideoEntity> search(VideoSearch videoSearch){

    if (StringUtils.hasText(videoSearch.name()) && StringUtils.hasText(videoSearch.description())){
        Sort sorting = Sort.by("name").ascending();
        return repository.findByNameContainsOrDescriptionContainsAllIgnoreCase(videoSearch.name(), videoSearch.description(),sorting);
    }

    if (StringUtils.hasText(videoSearch.name())){
        return repository.findByNameContainsIgnoreCase(videoSearch.name());
    }

    if (StringUtils.hasText(videoSearch.description())){
        return repository.findByDescriptionContainsIgnoreCase(videoSearch.description());
    }
    return Collections.emptyList();
}
// ... cutted

Another resource

Sumber daya luar yang berisikan informasi bagaimanya menyortir data pada Spring spring data sorting

Limiting Query Result

Selain sorting, kita juga dapat membatasi hasil dari query data, dibawah ini adalah beberapa opsi yang dapat kita berikan pada costume finder;

  • First atau Top: Mengambil data pertama dari result set. Contoh findFirstByName(String name) atau findTopByDesc(String desc).
  • FirstNNN atau TopNNN: Mengambil data NNN pertama dari result set. Contoh findFirst10ByName(String name) atau findTop3ByDesc(String desc).
  • Distinct: Mengambil data yang memiliki krekteria yang unik saja. Contoh findDistinctByName(String name).
  • Pageable: Meminta banyak data pada satu halaman. Kita juga dapat menggunakan Sorting parameter pada Pageable.

Mari kita gunakan paging and sorting. Pertama kita harus mengubah method pada repostory class agar dapat menerima parameter Pageable.

Code

public interface VideoRepository extends JpaRepository<VideoEntity, Long> {

    List<VideoEntity> findByNameContainsOrDescriptionContainsAllIgnoreCase(String partialName, String partialDescription, Sort sort);

    List<VideoEntity> findByNameContainsIgnoreCase(String partialName, Pageable pageable);

    List<VideoEntity> findByDescriptionContainsIgnoreCase(String partialDescription);

}

Selanjutnya mari kita rubah class service yang memanggil interface method tersebut. Kita akan membuat function baru agar mengembalikan Page<VideoEntitiy>.

Code

// ... cutted
public Page<VideoEntity> searchUsePage (VideoSearch videoSearch){
    if (StringUtils.hasText(videoSearch.name()) && StringUtils.hasText(videoSearch.page())){
        // Create instance of sort method
        Sort sorting = Sort.by("name").ascending();

        // Set paging and put sorting on ot
        Pageable pageable = PageRequest.of(Integer.parseInt(videoSearch.page()), 4,sorting);
        // pass it to repository method
        return repository.findByNameContainsIgnoreCase(videoSearch.name(), pageable);
    }
    return Page.empty();
}
// ... cutted

Diatas kita menentapkan setiap halaman yang diminta oleh user hanya menampilkan 4 baris data

Kita juga harus merubah class record VideoSearch.java agar bisa menerima request page.

Code

record VideoSearch(String name, String description, String page) {}

Kita membuat controller baru, karena controller tersebut akan mengirim attribute current page dan total page kepada user serta merujuk ke template index-page

Code

@PostMapping("/search-paging")
public String searchAndPaging(@ModelAttribute VideoSearch search, Model model){
    Page<VideoEntity> searchResult = videoService.searchUsePage(search);

    // Display maximum page can enter by user
    model.addAttribute("maxPage", searchResult.getTotalPages()-1);

    // Display current page of user
    model.addAttribute("currentPage", search.page());

    // Display result
    model.addAttribute("videos", searchResult);
    return "index-page";
}

MasyaAllah, the final touch, kita buat index-page.mustache agar user dapat memasukan page, halaman yang ingin ditampilkan serta menampilkan total halaman dan halaman saat ini.

Code

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<ol>
    <ul><a href="/">multi-field-search</a> </ul>
    <ul><a href="/paging">search-paging</a> </ul>
</ol>
<form action="/search-paging" method="post">
    <table>
        <tr>
            <td><label for="name">Name:</label></td>
            <td><input type="text" name="name"></td>
        </tr>
        <tr>
            <td>
                <label for="description">Description:</label>
            </td>
            <td>
                <input type="text" name="description">
            </td>
        </tr>
        <tr>
            <td>
                <label for="description">Page:</label>
            </td>
            <td>
                <input  type="number" name="page">
            </td>
        </tr>
    </table>
    <button type="submit">Search</button>
</form>
<div>
    <p>Pages <b>{{#currentPage}}{{currentPage}}{{/currentPage}}</b>of <b>{{#maxPage}}{{maxPage}}{{/maxPage}}</b></p>
</div>
<ul>
    {{#videos}}
        <li>{{name}} {{description}}</li>
    {{/videos}}
</ul>
</body>
</html>
and here the result

Result Paging

Selain membuat costume finders, kita juga dapat membuat costume lainnya, seperti existBy, deleteBy dan countBy method. Dibawah ini adalah sebagian dari costume query selain costume finders.

  • countByName (String name): Menjalankan query dengan operator COUNT. Method ini mengembalikan int, bukan domain typenya. SELECT COUNT(*) FROM [table] WHERE name = ?
  • existByDescription(String desc): Menjalankan query dan mengembalikan apakah result empty atau tidak
  • deleteByTag(String tag): Delete data dengan tag yang sesuai dengan parameter. DELETE FROM [table] WHERE flag ?

Another resource

Sumber daya luar yang berisikan informasi bagaimanya menyortir data pada Spring pagination-sorting

Using Query By Example

Query By Example membuat kita dapat membangung sebuah probe, sebuah instance dari domain object. Kita mengisi fields yang ada dengan kriteria yang kita ingin implementasi dan mengabaikan yang tidak kita inginkan dengan nilai empty (null).

Sebelumnya kita membuat costume finder dengan opsi mengisi field nama atau description. Namun bagaimana jika kita ingin membuat sebauh costume finder dengan membuat user hanya mengisi satu field dan mencari di kedua data nama dan descrption. Mari kita gunakan Query By Example.

Pertama kita buat dahulu class DTO (Data Transfer Object) untuk menerima nilai masukan dari user. Buat sebuah file dengan nama UniversalSearch.java

Code

record UniversalSearch(String value){}

Selanjutnya kita buat template yang digunakan user untuk memasukan nilia yang ingin dicari. Kita buat template dengan nama index-universal.mustache pada folder resources/template

Code

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<ol>
    <ul><a href="/">multi-field-search</a> </ul>
    <ul><a href="/paging">search-paging</a> </ul>
    <ul><a href="/universal">search-universal</a> </ul>
</ol>
<form action="/universal-search" method="post">
    <table>
        <tr>
            <td><label for="name">Search:</label></td>
            <td><input type="text" name="value"></td>
        </tr>
    </table>
    <button type="submit">Search</button>
</form>
<table>
    <tr>
        <th>Name</th>
        <th>Description</th>
    </tr>
    {{#videos}}
        <tr>
            <td>
                {{name}}
            </td>
            <td>
                {{description}}
            </td>
        </tr>
    {{/videos}}
</table>
</body>
</html>

Oke, sekarang mari kita buat controller untuk mengurusi rooting HTTP ke template dan menaruh model attribute.

Code

// ... cutted
@PostMapping("/universal-search")
    public String searchUniversal(@ModelAttribute UniversalSearch search, Model model){
        List<VideoEntity> searchResult = videoService.unversalSearch(search);

        // Display result
        model.addAttribute("videos", searchResult);
        return "index-universal";
    }
// ... cutted

Kita lihat pada List<VideoEntity> searchResult = videoService.unversalSearch(search);. Kita memanggil method pada class service. Mari kita membuat probe pada file service tersebut.

Code

// Universal search
    public List<VideoEntity> unversalSearch (UniversalSearch universalSearch){
        // Creating probe
        VideoEntity probe = new VideoEntity();

        if (StringUtils.hasText(universalSearch.value())){
            // Jadi string value akan mencari di kedua field name dan description

            // Search partial name
            probe.setName(universalSearch.value());

            // Search partial desc
            probe.setDescription(universalSearch.value());
        }

        // Create ExampleMatcher
        /**
         * Ignore Case
         * Contains
         */
        ExampleMatcher exampleMatcher = ExampleMatcher.matchingAny()
                .withIgnoreCase()
                .withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING);

        // Doing query by Example and setup ExampleMatcher
        Example<VideoEntity> videoEntityExample = Example.of(probe,exampleMatcher);

        return repository.findAll(videoEntityExample);
    }

Hmmm, penjelasanya baca pada komen diatas yah. 😄 😄 😄 😄 😄 😄

Using Costume JPA

....... I will add its later insyaAllah

Hal penting dalam perubahan Entitiy yang mempengaruhi Schema SQL

Catatn ini dibuat ketika saya ingin menambahkan OnDelete pada sebua entity. Namun ternyata tidak ada perubahan yang terjadi setelah saya mengambahkan OnDelete(action=Action.CASCADE). Padahal pada propetries saya juga sudah mengatur spring.jpa.hibernate.ddl-auto= update dengan nilai Update. Ternyata disini lah penjelasannya.

Detail tipe auto dll

Sebagai catatan, properti spring.jpa.hibernate.dll-auto adalah Spesifikasi dari Spring Data JPA dan sebagai penyesuaian sebuah nilai yang diberikan ke Hibernate.

Nilai tersebut diantaranya dalam bentuk create, create-drop, validate dan update pada dasarnya mempengaruhi bagaimana alat schema management akan memanipulasi database schema saat aplikasi dimulai, dijalankan.

Sebagai contoh, operasi update akan melakukan query JDBC driver's API untuk mendapatkan metadata database dan selanjutnya Hibernate membandingkan objek model yang dibuat berdasarkan hasil bacaan dari anotasi yang ada pada class-class atau pemetaan HBM XML dan akan melakukan percobaan penyesuaian schema on-the-fly.

Contoh mendalamnya lagi, operasi update akan melakukan penambahan kolom baru, constraints, dan sebagainya namun tidak akan pernah menghapus column atau constraint yang sudah ada sebelumnya namun tidak lagi menjadi bagian dari object model dari session saat aplikasi berjalan.

Secara khusus pada skenario test case, kita akan lebih baik dan disaranakan menggunakan operasi create-drop sehingga dibelakan layar schema akan dibuat, test case akan menambahkan data untuk pengujuan, dan menjalankan test tersebut dan setelah test case selesai data akan dhapus termasuk schema yang akan di drop sehingga membersihkan total database.

Pada saat pengembangan khususnya, banyak dari develpoer menggunakan nilai update agar secara otomatis memodifikasi schema ketika aplikasi di restart (dijalankan ulang). Namun perlu dipahami bahwa, operasi ini tidak akan menghapus kolom atau cosntrain yuang sudah ada sebelumnya.

Dan yang terakhir, pada server production, sangat2 disaranakn menggunakan operasi none atau ringkasnya jangan memberikan nilai apapun itu pada property. Mengapa ? karena umumnya untuk Database Administratir untuk meninjau kemablai script migrasi atas perubahan yang terjadi pada database, terutama jika database kita digunakan secara bersama kepada beberapa service dan aplikasi.

Warning

Pada buku ini mengenai JPA sangat terbatas, insyaAllah akan ada catatan yang saya buat yang diambil dari sumber lain. Diantaranya mengenai

  1. Menampilkan generate query
  2. Select JOIN table

Dapat melihat ke sini JPA,RestFullAPI