Querying Data with Spring Boot
InsyaAllah pada bagian catatan ini akan membahas topik-topik, diantaranya;
- Adding Spring Data to an existing Spring Boot application
- DTOs, entities, and POJOs
- Creating a Spring Data repository
- Using custom finders
- Using Query By Example to find tricky answers
- Using the custom Java Persistence API (JPA)
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
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 sediakanthis.id=null
, artinya sebauh construtor yang dibuat untuk membuat entries baru pada database. Jadi, ketikaid
bernilainull
, 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
Penjelkasan kode diatas sebagai berikut;
- Interface tersebut
extends
class#java JpaRepository
dengan dua tipe generic parameter,VideoEntyty
danLong
. 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
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
danOr
dapat digunakan untuk menggabungkan multiple property expressions. Kita juga dapat menggunakanBetween
,LessThan
, andGreaterThan
- You can apply
IsStartingWith
,StartingWith
,StartsWith
,IsEndingWith
,EndingWith
,EndsWith
,IsContaining
,Containing
,Like
,IsNotContaining
,NotContaining
, andNotContains
- You can apply
IgnoreCase
against a single field, or if you want to apply it to all properties, useAllIgnoreCase
at the end - You can apply
OrderBy
withAsc
orDesc
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
...// 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
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
atauTop
: Mengambil data pertama dari result set. ContohfindFirstByName(String name)
ataufindTopByDesc(String desc)
.FirstNNN
atauTopNNN
: Mengambil data NNN pertama dari result set. ContohfindFirst10ByName(String name)
ataufindTop3ByDesc(String desc)
.Distinct
: Mengambil data yang memiliki krekteria yang unik saja. ContohfindDistinctByName(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
.
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
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 mengembalikanint
, bukan domain typenya.SELECT COUNT(*) FROM [table] WHERE name = ?
existByDescription(String desc)
: Menjalankan query dan mengembalikan apakah result empty atau tidakdeleteByTag(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
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
- Menampilkan generate query
- Select JOIN table
Dapat melihat ke sini JPA,RestFullAPI