"Welcome To Ashok IT" "Spring Boot and MicroServices" Topic : Spring Data JPA - Generators Date : 12/04/2025 (Session - 26) _____________________________________________________________________________________________________________________________ Last Session ============ CrudRepoistory Interface Methods ================================ 1) T save(T t) ::: This method is used for Saving given entity (or) Inserting Record. 2) Iterable saveAll(Iterable items) ::: This method is used for saving group of entities. NOTE ==== * Iterable is root interface of Collection interface and came in the version of Java 1.5 * Iterable interface provides capability processing the collection object using "Enhanced For Loop" which came in the version of Java 1.5. 3) Optional findById(Serializable id) ::: To retreive record based on the given primary key value. NOTE ==== * Optional is an utility class from java8 Version which helps us to avoid the null checks in Java program. * Optional Class contains some utility methods to check whether object is present or not & We can get the object from optional object as below i) boolean isPresent() ii) T get(); 4) Iterable findAllById(Iterable ids) ::: To retreive records based on given primary key values. 5) Iterable findAll() ::: To Retreive all the records from table. 6) void delete(T t) ::: Deleting record based on given entity. 7) void deleteById(Serializable id) ::: Deleting record based on given primary key 8) void deleteAllById(Iterable ids) ::: Deleting records based on given primary key values . 9) void deleteAll() ::: Deleting all records from table with out primary key 10) void deleteAll(Iterable objects) ::: Deleting all records from table with out primary key 11) int count() :::: To get total records as count from table. 12) boolean existsById(Serializable id) ::: Check whether the record is existed or not for given primary key. Today Session ============== 1) spring.jpa.show-sql ====================== * This property will displays underlying sql queries used by ORM Framework. * By default this entry value as "false" means it will not display underlying SQL Queries on console, If we make it as true means will displayed underlying sql queries on console Example ======= spring.jpa.show-sql=false(default) spring.jpa.show-sql=true OUTPUT ====== Hibernate: select c1_0.customer_id, c1_0.contact_no, c1_0.email, c1_0.location, c1_0.name from shopping_customers c1_0 2) spring.jpa.properties.hibernate.format_sql ============================================= * This property is used to display underlying SQL Queries in structured format (or) Formatted. * By default value for this entry is "false" OUTPUT ====== Hibernate: select c1_0.customer_id,c1_0.contact_no,c1_0.email,c1_0.location,c1_0.name from shopping_customers c1_0 * If we change the value for above entry as "true" OUTPUT ====== Hibernate: select c1_0.customer_id, c1_0.contact_no, c1_0.email, c1_0.location, c1_0.name from shopping_customers c1_0 3) spring.jpa.hibernate.ddl-auto ================================= * In the earlier we just created the Database table manually through SQL Developer/SQL Command Line interface. * When we are working With ORM We no need to create the Database Table manually, Instead of this we need to add configuration in application.properties for creating Database table automatically during application execution. Example : ========= spring.jpa.hibernate.ddl-auto=create,create-drop,update,validate,none 1) create ::: First will drop the existing the table and then always will create new table. 2) create-drop ::: First will drop the existing the table and then will perform creating table and populating data will drop table immediately during startup only by observing log messages. 3) validate ::: Just Verifying the schema whether database tables present or not. 4) update ::: If table is not available then only will create otherwise it will reuse the existing table. 5) none ::: Programmer need to create the database table manually. Recommended value ================= spring.jpa.hibernate.ddl-auto = update * If we are providing the value for Primary key column means will have chance of getting "Constraint Violation exeception", if user is trying to insert record with same primary key value. * Inorder to overcome the above problem we have two solution 1) Always primary key column value should be auto generate from Database side. Ex: Oracle(Sequence), MySQL(AutoIncrement) Sequence Creation ================= *** create sequence start with increment by Ex: create sequence demo_sequence start with 1000 increment by 1; *** To select the next val from sequence need to use below command Ex: select demo_sequence.nextval from dual; *** To select the current val from sequence need to use below command Ex: select demo_sequence.currval from dual; *** Utilizing the Sequence while inserting the record into database table Ex: insert into shopping_customers values(demo_sequence.nextval,'test@gmail.com','Hyderabad','Test4'); 2) Always primary key column value should be auto generate through ORM Framework. Ex: Generators Generators ========== * Basically in application development will have multiple database tables. * Each Database table will have mandatorly primary key column which is combination of two constraints i.e.,Unique + not null constraint. * While inserting records into database table, If end user supplied primary key value might have chance for entering duplicate value for primary key column. * To Overcome this problem ORM Framework provided the generators concept. * Generators are used in application for generating the Primary key column value based on some mechanism supported by database vendor. * When we use generators in application before saving record primary key value will be generated with in application then record will be inserted into table along with primary key. * ORM Will support's the four types of Generators are as below 1) AUTO 2) SEQUENCE 3) IDENTITY 4) TABLE * We can use the following annotation @GeneratedValue helps for generating value for primary key based on strategy defined. * @GeneratedValue annotation should be defined on top of primary key column field in entity class. ************************ 1) GenerationType.AUTO ************************ >> This is the default generation type strategy for generating the primary key value of Database column. >> We can define the auto strategy on top of the primary key field in Entity Class with below annotation @Id @GeneratedValue(strategy=GenerationType.AUTO) private Integer productId; >> If we are using Oracle database internally Hibernate will create sequence database object with the name of hibernate_sequence. Ex: create sequence hibernate_sequence starts with 1 and increment by 1; >>>> SpringBoot 2.7.X version create sequence shopping_customer_seq start with 1 increment by 50 >>>> Spring Boot 3.X Table specific Sequence. create sequence mahesh_customers_seq start with 1 increment by 50 >>>>>> Spring Boot 3.X Table Specific Sequence. >> Before inserting the record into database table Hibernate will select value for hibernate_sequence/table specific sequence and insert into primary key column value. Ex: select hibernate_sequence.nextval from dual; >>>>>>> SpringBoot 2.7.x Version select shopping_customers_seq.nextval from dual; >>>>>>> SpringBoot 3.x Version insert into shopping_customers(?,?,?,?,?); >> If we are using MYSQL database internally Hibernate Will create table with name of Hibernate_sequence because MySQL doesn't supports the sequences concept and inorder to generate the primary key column value in MYSQL will have auto increment facility. create table hibernate_sequence( next_val bigint; ); insert into hibernate_sequence values(1); NOTE ==== Hibernate: create table shopping_customers ( customer_id integer not null, contact_no varchar(255), email varchar(255), location varchar(255), name varchar(255), primary key (customer_id) ) engine=InnoDB Hibernate: create table shopping_customers_seq ( next_val bigint ) engine=InnoDB Hibernate: insert into shopping_customers_seq values ( 1 ) Hibernate: select next_val as id_val from shopping_customers_seq for update Hibernate: update shopping_customers_seq set next_val= ? where next_val=? Hibernate: insert into shopping_customers (contact_no, email, location, name, customer_id) values (?, ?, ?, ?, ?) >> Before inserting the record into database table Hibernate will select value for hibernate_sequence table and insert into primary column value. Example Application =================== Customer.java ============= package com.ashokit.enities; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name="mahesh_cutomers") public class Customer { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Integer customerId; private String customerName; private String customerLocation; public Integer getCustomerId() { return customerId; } public void setCustomerId(Integer customerId) { this.customerId = customerId; } public String getCustomerName() { return customerName; } public void setCustomerName(String customerName) { this.customerName = customerName; } public String getCustomerLocation() { return customerLocation; } public void setCustomerLocation(String customerLocation) { this.customerLocation = customerLocation; } @Override public String toString() { return "Customer [customerId=" + customerId + ", customerName=" + customerName + ", customerLocation=" + customerLocation + "]"; } } CustomerDao.java ================ package com.ashokit.dao; import org.springframework.data.repository.CrudRepository; import com.ashokit.enities.Customer; public interface CustomerDao extends CrudRepository { } Application.java ================ package com.ashokit; import java.util.Arrays; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import com.ashokit.dao.CustomerDao; import com.ashokit.enities.Customer; @SpringBootApplication public class Application implements CommandLineRunner{ @Autowired private CustomerDao customerDao; public static void main(String[] args) { SpringApplication.run(Application.class, args); } @Override public void run(String... args) throws Exception { //inserting the record for an customer Customer c = new Customer(); c.setCustomerName("Mahesh"); c.setCustomerLocation("Hyderabad"); Customer c2 = new Customer(); c2.setCustomerName("Ashok"); c2.setCustomerLocation("Bangalore"); Iterable savedCustomers = customerDao.saveAll(Arrays.asList(c,c2)); savedCustomers.forEach(cust -> System.out.println(cust)); } } application.properties ====================== #configuring the Database properties spring.datasource.driver-class-name=oracle.jdbc.OracleDriver spring.datasource.url=jdbc:oracle:thin:@localhost:1521:xe spring.datasource.username=system spring.datasource.password=manager #Hibernate Configuration spring.jpa.hibernate.ddl-auto=update spring.jpa.show-sql=true ******************************** Problem With hibernate_sequence ******************************** ShoppingCustomers >>>>>> shopping_customers(DBTable) >>>>>> hibernate_sequence >>>>> Oracle Database ShoppingEmployee >>>>>> shopping_employees(DBTable) >>>>>> hibernate_sequence >>>>> Oracle Database 1) You Performed 5 insertions into shopping_customers DB Table >>>>>> CustomerIds(1,2,3,4,5) 2) You Performed 5 inserstion into shopping_employees DB Table >>>>>> employeeids(6,7,8,9,10) 3) You Performed 5 insertions into shopping_customers DB Table >>>>>> customerIds(11,12,13,14,15) 4) You Performed 5 insertions into shopping_employees DB Table >>>>>> employeeids(16,17,18,19,20) 5) Viewing the data for shopping_customers :1,2,3,4,5,11,12,13,14,15 6) Viewing the data for shopping_employees :6,7,8,9,10,15,16,17,18,19,20 If you observe the data for above two tables primary key column values are not in sync i.e.,Data Inconsistency. Inorder to overcome this problem we need to create independent sequence per database table. shopping_customers >>>>> shopping_customers_sequence >>>> GenerationType.SEQUENCE shopping_employees >>>>> shopping_employees_sequence >>>> GenerationType.SEQUENCE