Block 3
Block 3
Structure Page No.
9.0 Introduction
9.1Objectives
9.2 Spring Boot: An Overview
9.2.1 Spring Boot Working and Annotations
9.2.2 Spring Boot Starter
9.2.3 Spring Boot Project Structure
9.2.4 Spring Boot Runners
9.2.5 Spring Boot Web Application Using Thymeleaf
9.3 Spring Boot DevTools and Spring Boot Actuator
9.3.1 Spring Boot DevTools
9.3.2 Spring Boot Actuator
9.3.3 Spring Boot Actuator Example
9.4 Spring Boot- Application Properties
9.4.1 Command Line Properties
9.4.2 Properties File
9.4.3 YAML File
9.4.4 Externalized Properties
9.4.5 @Value annotation
9.4.6 Active Profile
9.4.7 Spring Active Profile in application.yml
9.5 Running Spring Boot Apps from command line
9.5.1 Running the Code with Maven in Exploded Form
9.5.2 Running the Code as a Stand-Alone Packaged Application
9.5.3 Application Packaging as WAR and Deployment on Tomcat
9.6 Summary
9.7 Solutions/Answer to Check Your Progress
9.8 References/Further Reading
9.0 INTRODUCTION
Fast, secured and cost-effective development of software plays a vital role in the
growth of an organization. Java has been the popular choice for many enterprises and
programmers since the mid 90’s for designing and developing software. Hence, lots of
frameworks are being developed to ease the software development using Java.
In order to make the software development easy, fast and effective several
frameworks have been introduced such as Struts, Spring and ORM tools such as
Toplink, Hibernate, Eclipse Link, Ibatis.
1
Introduction To Spring • Import the specified Spring version compatible third-party libraries such as
Boot hibernate, Jackson etc.
• Configure web layer beans such as view resolver, resource manager etc.
The spring team considered simplifying the routine configuration and facilitating the
developers with some utility that automates the configuration process and speeds up
the spring-based application's build and deployment process. Spring has evolved a lot
in recent years and introduced many new modules such as Spring Boot, Spring
Security, Spring Cloud, Spring Data etc.
9.1 OBJECTIVES
Spring Boot is an extension of the Spring framework that takes one step ahead and
simplifies the configuration in order to fasten the development and execution of the
spring application. It eliminates the boilerplate configuration required for a spring
application. It is a module that enriches the Spring framework with Rapid Application
Development (RAD) feature. It provides an easy way to create a stand-alone and
production ready spring application with minimum configurations. Spring Boot
provides comprehensive infrastructure support for the development and monitoring of
the enterprise-ready applications based on micro services. Spring Boot is a
combination of Spring framework with auto-configuration and embedded Servers.
Spring Boot provides a vast number of features and benefits. A few of them are as
follows:
2
2) Spring Boot starter eases the dependency management and application Spring Boot and Hibernate
(ORM)
configuration
3) It simplifies the application deployment by using an embedded server
4) Production ready features to monitor and manage applications, such as health
checks, metrics gathering etc.
5) Reduces the application development time and run the application
independently
6) Very easy to understand and develop Spring application
7) Increases productivity and reduces the cost
A class with the main method and annotated with @SpringBootApplication is the
entry point of the Spring Boot application. Spring Boot auto-configures all required
configurations. It performs auto-configuration by scanning the classes in class-path
annotated with @Component or @Configuration. @SpringBootApplication
annotation comprising the following three annotations with their default values-
• @EnableAutoConfiguration
• @ComponentScan
• @Configuration
@EnableAutoConfiguration
As the name implies, it enables auto-configuration. It means Spring Boot looks for
auto-configuration beans on its class-path and automatically applies them. For
example, if H2 dependency is added and you have not manually configured any
database connection beans, then Spring will auto-configure H2 as an in-memory
database.
The @EnableAutoConfiguration annotation should be applied in the root package so
that every sub-packages and class can be examined.
@ComponentScan
The @ComponentScan annotation enables Spring to scan for things like
configurations, controllers, services, and other components we define. By default, the
scanning starts from the package of the class declaring @ComponentScan. The
component scanning can be started from specified packages by defining
basePackageClasses, basePackages attributes into @ComponentScan. The
@ComponentScan annotation is used with @Configuration.
@Configuration
The @Configuration annotation is used for annotation-based configuration into the
Spring application. A class annotated with @Configuration indicates that the class
declares one or more @Bean methods and can be processed by Spring container to
generate bean definitions and service requests for those beans at runtime.
3
Introduction To Spring classes. Hence, @ConditionalOnClass loads a bean only if a certain class is on the
Boot classpath and @ConditionalOnMissingClass loads a bean only if a certain class is not
on the classpath.
@ConditionalOnProperty
The annotation is used to conditionally create a Spring bean depending on the
configuration of a property.
@Bean
DataSourcedataSource()
// ...
The DataSource bean will be created only if property usepostgres exists and it has
value as local.
@ConditionalOnResource
The annotation is used to conditionally create a Spring bean based on the presence or
absence of resources. The SpringConfig class beans will be created if the resource
log4j.properties file is present.
@Configuration
@ConditionalOnResource(resources = { "log4j.properties" })
class SpringConfig
{
@Bean
public Log4j log4j()
{
return new Log4j();
}
}
Before describing Spring Boot Starter, the following section explains all the required
things to develop a web application.
4
Development of a web application using Spring MVC will require identifying all the Spring Boot and Hibernate
required dependencies, compatible versions and how to connect them together. (ORM)
Followings are some of the dependencies which are used in Spring MVC web
application. For all the dependencies we need to choose the compatible version
dependencies.
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.2.2.RELEASE</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.5.3</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.0.2.Final</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
5
Introduction To Spring Dependency management is a very important and complex process in any project.
Boot Manual dependency management is error-prone, non-ideal and non-suggestible. To
focus more on aspects apart from dependency management in web application
development will require some solution that addresses compatible dependency
management problems.
Spring Boot starters are the dependency descriptor that addresses the problem of
compatible versions of dependency management. Spring Boot Starter POMs are a set
of convenient dependency descriptors that you can include in your application. You
get a one-stop-shop for all the Spring and related technology that you need from
Spring Boot starters. Spring Boot provides a number of starters that make
development easier and rapid. Spring Boot starters follow a similar naming pattern as
spring-boot-starter-*, where * denotes a particular type of application. For instance,
developing a rest service that requires libraries like Spring MVC, Tomcat, Log and
Jackson, a single Spring Boot starter named spring-boot-starter-web needs to be
included. Spring Boot provides many numbers starter, and a few of them are listed
below-
spring-boot-starter-jdbc It is used for JDBC with the Tomcat JDBC connection pool.
Spring Boot provides a high degree of flexibility in code layout. However, there are
certain best practices that will help to organize the code for better readability.
In Spring Boot, default package declaration is not recommended since it can cause
issues such as malfunctioning of auto-configuration or Component Scan. Spring Boot
annotationslike:
@ComponentScan,
@EntityScan,
6
@CoonfigurationP
PropertiesScan, and Spring Booot and Hibernatte
(ORM)
@SppringBootAppplication
The @SpringBoot
@ tApplication annotation
a triiggers compoonent scanninng for the currrent
packkage and its suub-packages. Therefore, thhe main class of the projectt should residde in
the base
b package tot use the impplicit componnents scan of Spring Boot.
In thhe above codee structure, coontroller, mod del, repositoryy and servicee are sub-packkage
of base
b packagge com.igno ou.springbooot.learning. All the components
c and
confifigurations aree eligible for implicit
i scann
ning with maiin class as below:
pack
kage com.ignou.springb
boot.learning;
impo k.boot.SpringApplicati
ortorg.springframework ion;
impo
ortorg.springframework
k.boot.auto
oconfigure.S
SpringBootA
Application;
@Spr
ringBootApplication
publ
lic class SpringbootLe
earningApplication
{
static void main(Strin
public s ng[] args)
{
pplication.run(Springb
SpringAp bootLearnin
ngApplicatio
on.class,
args
s);
}
}
7
7
Introduction To Spring Spring Boot has a high degree of flexibility. Thus, it allows us to relocate the
Boot scanning elsewhere by specifying the base package manually.
package com.ignou.springboot.learning;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication(scanBasePackages= {"com.ignou.springboot"})
public class SpringbootLearningApplication
{
public static void main(String[] args)
{
SpringApplication.run(SpringbootLearningApplication.class, args);
}
}
In above package structure, component and configuration packages are not sub-
package of main class. Thus, scanning location has been explicitly defined as
@SpringBootApplication(scanBasePackages= {"com.ignou.springboot"})
Both interfaces are Functional Interface. If any piece of code needs to be executed
when Spring Boot Application starts, we can implement either of these functional
interfaces and override the single methodrun.
8
Application Runner Spring Boot and Hibernate
(ORM)
Spring bean which implements the ApplicationRunnerinterfaces in a Spring Boot
Application, the bean gets executed when application is started. ApplicationRunner
example is as following-
packagecom.ignou.springboot.learning;
importorg.springframework.boot.ApplicationArguments;
importorg.springframework.boot.ApplicationRunner;
importorg.springframework.stereotype.Component;
@Component
publicclassApplicationRunnerImplimplementsApplicationRunner
{
@Override
publicvoid run(ApplicationArgumentsargs) throws Exception
{
System.out.println("Application Runner Executed.");
}
}
The execution result of Spring Boot application having the above component is shown
below, and you can observe that the bean implementing ApplicationRunner is
executed just after the application starts.
The Command LineRunner interface is also meant for the same purpose as
ApplicationRunner interface. Spring bean which implements the
CommandLineRunner interface in a Spring Boot Application, the bean gets executed
when the application is started. CommandLineRunner example is as following-
packagecom.ignou.springboot.learning;
importorg.springframework.boot.CommandLineRunner;
importorg.springframework.stereotype.Component;
@Component
9
Introduction To Spring publicclassCommandLineRunnerImplimplementsCommandLineRunner
Boot
{
@Override
publicvoid run(String... args) throws Exception
{
System.out.println("Command Line Runner executed");
}
}
Execution result of Spring Boot application with the above component is shown
below and you can observe that the bean implementing ApplicationRunner is executed
just after application starts.
The previous sections have described the basic concepts of Spring Boot. This section
explains the process of creating a “Hello World” website using the Spring Boot
concepts. Required tools and software are as follows:
• Eclipse
• Maven
• Spring Boot
• JDK 8 or above
Step 1: Create a Spring Boot Project using Spring Initializr. Visit at
https://start.spring.io/ and generate the Spring Boot project with added dependency.
For the project,Spring Web and Thymeleaf dependency will be used.
Figure 9.5: SpringBoot Project Initialization Using Spring Initializr
10
Step 2: Extract the generated project and Import this into eclipse as maven project. Spring Boot and Hibernate
Project structure is shown below. (ORM)
Figure 9.6: SpringBoot Project Structure
packagecom.example.demo.controller;
importorg.springframework.stereotype.Controller;
importorg.springframework.ui.Model;
importorg.springframework.web.bind.annotation.GetMapping;
importorg.springframework.web.bind.annotation.RequestMapping;
importorg.springframework.web.bind.annotation.RequestParam;
@Controller
publicclassHomeController
{
@RequestMapping(value="/")
public String home()
{
return"home";
}
@GetMapping("/greeting")
public String greeting(@RequestParam(name="name",
required=false,defaultValue="World") String name, Model model)
{
model.addAttribute("name", name);
return"greeting";
11
Introduction To Spring }
Boot }
Step 4: Thymeleaf is used as a view technology in this example. For both the end
point, add the corresponding HTML template file into src/main/resources/templates
home.html
<!DOCTYPEhtml>
<html>
<head>
<metacharset="ISO‐8859‐1"/>
<title>Spring Boot Web Application</title>
</head>
<body>
<h1>Welcome to Thymeleaf Spring Boot web application</h1>
</body>
</html>
greeting.html
<!DOCTYPEHTML>
<htmlxmlns:th="http://www.thymeleaf.org">
<head>
<title>Getting Started: Serving Web Content</title>
<metahttp‐equiv="Content‐Type"content="text/html; charset=UTF‐8"/>
</head>
<body>
<pth:text="'Hello, ' + ${name} + '!'"/>
</body>
</html>
Step 5: Now the project is ready to run. Run DemoApplication.java file as Java
Application in eclipse as shown below.
12
Access the endpoints, as mentioned in step 3, into the browser. You will get the Spring Boot and Hibernate
(ORM)
13
Introduction To Spring
Boot
14
Check Your Progress 1 Spring Boot and Hibernate
(ORM)
15
Introduction To Spring Spring Boot DevTools and Spring Boot Actuators are very important modules that
Boot enhance the development experience and increase productivity. These modules reduce
the developers’ effort and thus reducethe cost of the project.
Spring Boot DevTools was released with Spring Boot 1.3. DevTools stands for
developer tool. The aim of DevTools module is to enhance the application
development experience by reducing the development time of the Spring Boot
Application. During a web application development, a developer changes the code
many times and then restarts the application to verify the changed code.
DevToolsreduces the developer effort. It detects the code changes and restarts the
application automatically. DevTools can be integrated into a Spring Boot application
just by adding the following dependency into pom.xml.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring‐boot‐devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
• Automatic Restart
• Live Reload
• Property defaults
Automatic Restart: Auto-restart refers to the reloading of Java classes and configures
it at the server-side. While developing an application, a developer changes the code
frequently and to verify these changes, the steps build, deploy and restart of the server
is required. Spring Boot DevTools automates the build and deploys process, which
increases productivity. Files change in the class-path triggers Spring Boot DevTools
to restart the application. This auto-restart process reduces the time significantly to
verify the changes. Spring Boot uses two types of ClassLoaders:
• Base ClassLoader: This ClassLoader loads the classes which do not change.
E.g. Third-party jars
• Restart ClassLoader: This ClassLoader loads the classes which we are
actively developing
Live Reload: Live Reload or auto-refresh is also a very important feature provided by
Spring Boot DevTools. Spring Boot DevTools module also comes with an embedded
LiveReload server that can be used to trigger a browser refresh whenever a resource is
changed. For example, when a developer makes the changes into templates or other
resources, he/she has to refresh the browser to verify the changes. With the Live
Reload/Auto Refresh feature, developers do not need to press F5 to refresh the
browser. Thus, it enhances the development experience and increases productivity.
Enabling Live Reload in Spring Boot Application is pretty easy. Following steps are
required to enable it.
16
1) Add the dependency spring-boot-devtools to your project’s build file Spring Boot and Hibernate
(ORM)
(pom.xml).
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
Once the application is started, one can verify the LiveReload server into log.
browser.
Figure 9.11: Live Reload Extension
You can enable and disable the live reload by clicking on LiveReload as shown in
screenshot.
17
Introduction To Spring
Boot
spring.devtools.restart.additional-paths=/path-to-folder
18
Property Defaults: Spring Boot does a lot of auto configuration. It also includes Spring Boot and Hibernate
caching for performance improvement. Template technology Thymeleaf contains the (ORM)
property spring.thymeleaf.cache. DevTools disables the caching and allows us to
update pages without restarting the application. During the development, caching for
Thymeleaf, Freemarker, Groovy Templates are automatically disabled by DevTools.
Spring Boot Actuator is a sub-project of the Spring Boot framework. The Actuator
provides production-ready features such as application monitoring, Network traffic,
State of database and many more. Without any implementation, Actuator provides
production-grade tools. In Spring Boot application, Actuator is primarily used to
expose operational information about the running application such as info, health,
dump, metrics, env etc. It provides HTTP and JMX endpoints to manage and monitor
the Spring Boot application. There are three main features of Spring Boot Actuator-
• Endpoints
• Metrics
• Audit
Endpoints: The actuator endpoints enable us to monitor and interact with the
application. In Spring Boot 2.x, most of the endpoints of the Actuator are disabled. By
default, only two endpoints /health and /info are available. Other required endpoints
can be enabled by adding management.endpoints.web.exposure.include property into
application.properties. By default, all Actuator endpoints are now placed under
the /actuator path. Some of the important endpoints are listed below –
• /health provides the health status of the application
• /info provides general information about the application. It might be build
information or the latest commit information.
• /metrics provides metrics of application. Returned metrics include generic
metrics as well as a custom metric.
• /env provides the current environment properties.
Metrics: Spring Boot integrates the micrometer to provide dimensional metrics. The
micrometer is the instrumentation library that empowers the delivery of application
metrics from Spring. Metrics of the application can be accessed by /metrics endpoint.
Audit: Spring Boot provides a flexible audit framework that publishes events to
an AuditEventRepository. It automatically publishes the authentication events if
spring-security is in execution.
This section explains the required steps to integrate the Spring Boot Actuator into the
previously developed website into section 9.2.5. Add the spring-boot-starter-actuator
dependency into pom.xml –
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring‐boot‐starter‐actuator</artifactId>
</dependency>
19
Introduction To Spring
Boot
management.endpoints.web.exposure.include= *
21
Introduction To Spring …………………………………………………………………………………
Boot
……………………………….
3) Write a simple "Hello World" Spring Boot rest application.
…………………………………………………………………………………
…………………………………………………………………………………
…………………………………………………....................................………
…………………………………………………………………………………
……………………………….
server.port = 9090
spring.application.name = demoservice
Property server.port changes the port number on which the web application runs.
22
9.4.3 YAML File Spring Boot and Hibernate
(ORM)
Spring Boot also supports YAML based properties configuration. Properties file
application.yml can be used instead of application.properties. YAML is a convenient
format for specifying hierarchical configuration data. The application.yml file also
should be kept in src/main/resources directory. Sample application.yml file is shown
below-
server:
port: 9090
spring:
application:
name: demoservice
Spring Boot supports keeping properties file at any location. We can externalize the
properties file so that if any property is changed, a new build is not required. Just
application restart will take effect on the changed property. While executing the
application jar file, the following command-line argument is used to specify the
location of the property file.
-Dspring.config.location = C:\application.properties
Properties, defined for environment or application, can be fetched in java code using
@Value annotation. Syntax to use @Value annotation is shown below –
@Value(“${property_key}”)
@Value("${spring.application.name}")
String appName;
While running, if the property is not found, an exception is thrown. The default value
can be set while fetching the value using @Value annotation as follows-
@Value(“${property_key:default_value}”)
spring.application.name = demoservice
application-dev.properties
server.port = 9090
spring.application.name = demoservice
application-prod.properties
server.port = 9090
spring.application.name = demoservice
By default, Spring Boot uses application.properties file. But Spring Boot allows to set
the active profile and corresponding properties file that is used by Spring Boot. The
following command shows how to set an active profile while starting an application
from the command- line.
While running an application from eclipse IDE, the active profile can be set as shown
in the screenshot.
24
Spring Boot and Hibernate
(ORM)
25
Introduction To Spring Active profile can be checked in the log while starting the application.
Boot
YAML file allows active profile parameters to be kept into a single application.yml
file. Unlike multiple application.properties files, there is a single application.yml.
Delimiter (---) is used to separate each profile in an application.yml file. Sample
application.yml file is shown with active profile dev and prod.
server:
port: 9090
spring:
application:
name: demoservice
‐‐‐
server:
port: 8080
spring:
config:
activate:
on‐profile: dev
application:
name: demoservice
‐‐‐
server:
port: 8080
spring:
config:
activate:
on‐profile: prod
application:
name: demoservice
26
Spring Boot and Hibernate
9.5 RUNNING SPRING BOOT APPS FROM (ORM)
COMMAND LINE
This section describes a couple of ways to run a Spring Boot app from a command
line in a terminal window. Later it explains how to package the app as war and which
can be deployed on any application server such as Apache Tomcat, WebLogic, JBoss,
etc.
The Spring Boot Maven plugin is the recommended tool to build, test and package
the Spring Boot Application code. The plugin is configured by adding it into
pom.xml.
<build>
<plugins>
...
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
...
</plugins>
</build>
The Spring Boot Maven plugin has the ability to automatically deploy the web
application in an embedded application server. If spring-boot-starter-web
dependency has been included, plugin knows that Tomcat is required to run the code.
On execution of mvnspring-boot:run command in the project root folder, the plugin
reads the pom configuration. If a web application container is required, the plugin
triggers the download of Apache Tomcat and initializes the startup of Tomcat. The
command to run the Spring Boot application using maven plugin is as following –
mvnspring-boot:run
27
Introduction To Spring Execution of the above command starts the Spring Boot application and the produced
Boot log is shown.
Once the development phase is over, the application is moved to production, and we
need to package the application. Just include the Spring Boot Maven plugin and
execute the following command in order to package the application.
The execution of the above command packages the application and produces the jar
file into the target folder. The generated jar file can be executed using the following
command.
As you can notice, that –cp option and main class has been skipped into java –jar
command because the Spring Boot Maven plugin takes care of all these configurations
into the manifest file.
By default, Spring Boot builds a standalone Java application that can run as a desktop
application. The standalone Java application is not suitable for the environment where
installation of a new service or manual execution of an application is not allowed,
such as Production environment.
The Servlet containers require the applications to meet some contracts to be deployed.
For Tomcat the contract is the Servlet API 3.0. This section considers the example
used in section 9.2.5 and explains how the application can be packaged as WAR and
deployed into Tomcat.
First, change the packaging type as war into pom.xml with the following content.
<packaging>war</packaging>
28
@SpringBootApplication Spring Boot and Hibernate
(ORM)
publicclassDemoApplicationextendsSpringBootServletInitializer
{
publicstaticvoid main(String[] args)
{
SpringApplication.run(DemoApplication.class, args);
}
}
By default, generated war file name includes version number also. The Name of the
generated war can be modified with following –
<build>
<finalName>${artifactId}</finalName>
...
</build>
Execute the following command in order to build the Tomcat deployable war if
artifact id is demo, war file generated at target/demo.war. Follow the below steps in
order to deploy the generated war file on Tomcat.
29
Introduction To Spring …………………………………………………………………………………
Boot
…………………………………………………………………………………
……………………………………………....................................……………
…………………………………………………………………………………
……………………………….
4) Explain the Spring Boot application execution with Maven.
…………………………………………………………………………………
…………………………………………………………………………………
……………………………………………....................................……………
…………………………………………………………………………………
……………………………….
5) What are the steps to deploy Spring Boot web applications as JAR and WAR
files?
…………………………………………………………………………………
…………………………………………………………………………………
……………………………………………....................................……………
…………………………………………………………………………………
……………………………….
9.6 SUMMARY
This unit has described Spring Boot facilitates the developers to create a Spring based
web application with minimum lines of code since it provides auto configuration out-
of-the-box. This unit has explained the following:
30
• Spring Boot supports keeping properties files at any location. We can Spring Boot and Hibernate
externalize the properties file so that if any property is changed, a new build is (ORM)
not required.
• Spring Boot supports the concept of an active profile. There can be multiple
properties files corresponding to each environment. At run time, Spring Boot
selects the desired environment properties file based on active profile.
• Spring Boot application can be executed from command line with Spring
Boot Maven plugin using mvnspring-boot:run and can be executed as a
standalone application by java -jar <fileName>
Spring Boot provides a vast number of features and benefits. A few of them
are as follows:
3) Spring Boot starters are the dependency descriptor that addresses the problem
of compatible versions of dependency management. Starter POMs are a set of
convenient dependency descriptors that you can include in your application.
31
Introduction To Spring You get a one-stop-shop for all the Spring and related technology that you
Boot need from Spring Boot starters. Spring Boot provides a number of starters that
make development easier and rapid. Spring Boot provides many numbers
starter, and a few of them are listed below-
spring-boot-starter-web It is used for building web applications, including
RESTful applications using Spring MVC. It uses
Tomcat as the default embedded container.
spring-boot-starter-jdbc It is used for JDBC with the Tomcat JDBC
connection pool.
spring-boot-starter-validation It is used for Java Bean Validation with Hibernate
Validator.
spring-boot-starter-security It is used for Spring Security.
spring-boot-starter-data-jpa It is used for Spring Data JPA with Hibernate.
1) Spring Boot DevTools was released with Spring Boot 1.3. DevToolsstands for
developer tool. Aim of DevTools module is to enhance the application
development experience by improving the development time of the Spring
Boot Application. During a web application development, a developer
changes the code many times and then restarts the application to verify the
code changes. DevTools reduces the developer effort. It detects the code
changes and restarts the application. DevTools can be integrated into a Spring
Boot application just by adding the following dependency into pom.xml.
32
<dependency> Spring Boot and Hibernate
(ORM)
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
3) To create a simple Hello World rest application using Spring Boot, we need to
perform the below steps:
33
Introduction To Spring @RestController
Boot
publicclassHomeController {
@GetMapping(value="/")
public String index() {
return"Hello World!!";
}
-Dspring.config.location = C:\application.properties
2) Yes, we can change the port of the embedded tomcat server by using the
application properties file. In application.properties file, you must add a
property of “server.port” and assign it to any port you wish to. For example,
if you want to assign it to 8081, then you have to mention server.port=8081.
Once you mention the port number, the application properties file will be
automatically loaded by Spring Boot, and the required configurations will be
applied to the application.
34
Spring Boot and Hibernate
9.8 REFERENCES/FURTHER READING (ORM)
35
UNIT 10 CONFIGURATION OF
HIBERNATE(ORM)
10.0 INTRODUCTION
In computer science, object-relational mapping (ORM, O/RM, and O/R mapping tool)
is a programming technique for converting data between incompatible type systems
using object-oriented programming languages. ORM makes it possible to perform
CRUD (Create, Read, Update and Delete) operations without considering how those
objects relate to their data source. It manages the mapping details between a set of
objects and the underlying database. It hides and encapsulates the changes in the data
source itself. Thus, when data sources or their APIs change, only ORM change is
required rather than the application that uses ORM.
Hibernate is a pure Java object-relational mapping (ORM) and persistence framework
which maps the POJOs to relational database tables. The usage of Hibernate as a
persistence framework enables the developers to concentrate more on the business
logic instead of making efforts on SQLs and writing boilerplate code. There are
several advantages of Hibernate, such as:
• Open Source
• High Performance
• Light Weight
• Database independent
• Caching
• Scalability
• Lazy loading
• Hibernate Query Language (HQL)
Java Persistence API (JPA) is a specification that defines APIs for object-relational
mappings and management of persistent objects. JPA is a set of interfaces that can be
used to implement the persistence layer. JPA itself doesn’t provide any
implementation classes. In order to use the JPA, a provider is required which
implements the specifications. Hibernate and EclipseLink are popular JPA providers.
Spring Data JPA is one of the many sub-projects of Spring Datathat simplifies the
data access to relational data stores. Spring Data JPA is not a JPA provider; instead, it
1
Configuuration of wraps the JP PA provider and adds its own features like a no-code implemen ntation of
Hibernaate (ORM) the reposittory pattern n. Spring Daata JPA usees Hibernate as the defaault JPA
provider. JPAJ provider is configuraable, and otheer providers can also be uused with
Spring Dataa JPA. Spring Data JPA provides a complete absttraction over the DAO
layer into thhe project.
This unit ex
xplains only HHibernate in detail
d with itss architecture and sample examples.
This unit allso covers thee relationshipp between Sprring Data JPA A, JPA and Hibernate.
H
There are many
m similar CCrud operatioons available in Hibernate,, such as savee, persist,
saveOrUpd date, get and d load. Hibeernate entity state definees the behaviior of the
operations. Thus, one shoould study thee Hibernate entity states ass transient, persistent,
p
detached an nd removed very carefully y in order to have
h in-depthh insights for Hibernate
CRUD operrations.
This unit also covers thhe overview of Spring Data D JPA wiith its advanntages and
w this reducees the effort of a developerr to implemennt the data acccess layer.
explains how
The next un
nit covers Spriing Data JPAA in detail.
10.1 OBJECT
O TIVES
After going through this unit, you willl be able to:
• desscribe Hibernaate as ORM tool,
• expplain Hibernatte architecturre,
• usee Annotations in Hibernatee and Java-bassed Hibernatee configuratioon,
• usee Hibernate C CRUD operatiions such as save,s persist, saveOrUpdatte,
• diffferenciate bettween same taask performinng operations such asget VsV load
etc..,
• estaablish the relaationship betw
ween Spring D Data JPA, JPA A and Hibernnate, and
• usee Spring Data JPA.
10.2 HIBERN
H ATE OV
VERVIEW
W
Hibernate iss an open-soource Java peersistence fram mework creaated by Gavinn King in
2011. It sim
mplifies the ddevelopment of Java appllications to innteract with databases.
d
Hibernate iss a lightweigght, powerful and high-perrformance OR RM (Object Relational
R
Mapping) toool that simpllifies data creation, data manipulation an
nd data accesss.
The Java Persistence
P A
API (JPA) is a specificatioon that defines how to persist data
in Java applications.
a . Hibernate is a popuular ORM which w is a standard
implementaation of the JJPA specificaation with a few additionnal features specific
s to
Hibernate. Hibernate
H liees between Jaava Objects and databasee servers to hhandle all
persistence and retrieval of those objeects using apppropriate mechanisms andd patterns.
A schematicc diagram is shown
s in Figuure 10.1
Figure1
10.1 Hibernate O
ORM
2
10.2
2.1 Hibernaate Architeecture Spring Booot and Hibernatte
(ORM)
Hibeernate has fouur-layered archhitecture. Thee Hibernate inncludes manyy objects suchh as
persiistent objects,, session factoory, session, connection
c faactory, transacction factory,
transsaction etc. Hiigh-level archhitecture diaggram is shownn in Figure 100.2
A deetailed view of the Hiberrnate Applicaation Architeecture with some of the ccore
classses is shown in Figure 10.33
Figure10.3 Hibernate
H Dettailed Architecctural View
Con
nfiguration
An innstance of Coonfiguration allows
a the appplication to sppecify propertties and mappping
docuuments to be used
u when creeating a SessiionFactory. The
T Configuraation object iss the
first object whichh is being created in the Hibernate
H appllication. The Configuratioon is
3
3
Configuration of only an initialization-time object. Usually, a Hibernate application creates a single
Hibernate (ORM) Configuration, builds a single immutable SessionFactory and then instantiate Sessions
in threads servicing client requests. Configuration represents an entire set of mappings
of an application's Java types to an SQL database. The Configuration can be
configured either programmatically or using configuration file. The configuration file
can be either an XML file such as hibernate.cfg.xml or a properties file such as
hibernate.properties.
Xml based hibernate configuration for Mysql database is shown below-
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-5.0.dtd">
<hibernate-configuration>
<session-factory>
<property
name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property
name="hibernate.connection.url">jdbc:mysql://localhost:3306/test</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">root</property>
<property name="hibernate.connection.pool_size">10</property>
<property name="show_sql">true</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.current_session_context_class">thread</property>
</session-factory>
</hibernate-configuration>
Properties file base hibernate configuration for Mysql database is shown below-
hibernate.dialect= org.hibernate.dialect.MySQLDialect
hibernate.connection.driver_class= com.mysql.jdbc.Driver
hibernate.connection.url= jdbc:mysql://localhost:3306/test
hibernate.connection.username= root
hibernate.connection.password=root
hibernate.show_sql=true
hibernate.hbm2ddl=update
SessionFactory
4
Spring Boot and Hibernate
The Hibernate creates an immutable SessionFactory object using the Configuration (ORM)
object. SessionFactory is used to instantiate the session object in a thread to service
client requests. SessionFactory object is thread safe and used by all the threads of an
application.
SessionFactory object is per database using a separate configuration file. Thus, for
multiple databases, we will require to create multiple SessionFactory objects. The
SessionFactory is a heavyweight object, and it is created at the time of application
startup.
Session
The session object provides an interface to interact with the database from an
application. It is lightweight, which instantiates each time an interaction is required
with the database. Session objects are used to retrieve and save persistent objects. It is
a short-lived object which wraps the JDBC connection. It also provides a first-level
cache of data.
Transaction
A Transaction represents a unit of work with the database, and most of the RDBMS
supports transaction functionality. Transaction object provides a method for
transaction management. It enables data consistency and rollback in case something
wrong.
Query
Query objects use SQL or Hibernate Query Language (HQL) string to retrieve data
from the database and create objects. A Query instance is used to bind query
parameters, limit the number of results returned by the query, and finally to execute
the query.
Persistent Objects
These are plain old java objects (POJOs), which get persisted into the database by
hibernate. Persistent objects can be configured in configurations files
(hibernate.cfg.xml or hibernate.properties) or annotated with @Entity annotation.
First-level Cache
Cache is a mechanism that improves the performance of any application. Hibernate
provides a caching facility also. First-level cache is enabled by default, and it can’t be
disabled. Hibernate ORM reduces the number of queries made to a database in a
single transaction using First-level cache. First-level cache is associated with Session
object and it is available till the session object is alive. First-level cache associated
with session objects is not accessible to any other session object in other parts of the
application. Important facts about First-level cache is as followings-
• First-level cache scope is session. Once the session object is closed, the first-
level cache is also destroyed.
• First-level cache can’t be disabled.
• First time query for an entity into a session is retrieved from the database and
stored in the First-level cache associated with the Hibernate session.
• Query for an object again with the same session object will be loaded from
the cache.
• Session evict() method is used to remove the loaded entity from Session.
• Session clear() method is used to remove all the entities stored in the cache.
Second-level Cache
5
Configuration of Second-level cache is used globally in Session Factory scope. Once the session
Hibernate (ORM) factory is closed, all cache associated with it dies, and the cache manager is also
closed down. Working of Second-level cache is as followings-
• At first, the hibernate session tries to load an entity, then First-level cache is
looked up for cached copy of entity.
• If an entity is available in First-level cache, it is returned as a result of the load
method.
• If an entity is not available in First-level cache, Second-level cache is looked
up for cached copy of the entity.
• If an entity is available into Second-level cache, it is returned as a result of the
load method. But before returning the result, the First-level cache is being
updated so that the next invocation for the same entity can be returned from
the First-level cache itself.
• If an entity is not found in any of cache, the database query is executed, and
both the cache is being updated.
• Second level cache validates itself for modified entities, if the modification
has been done through hibernate session APIs.
6
Spring Boot and Hibernate
ANNOTATION (ORM)
@Entity
In JPA, POJOs are entities that represent the data that can be persisted into a database.
An entity represents the table in a database. Every instance of an entity represents a
row in the table. Let’s say there is a POJO named Student, which represents the data
of Student. In order to store the student records into a database, Student POJO must
be defined as an entity so that JPA is aware of it. This can be done by annotating
POJO class with @Entity annotation. The annotation must be defined at class level.
The Entity must have no-arg constructor and a primary key. The entity name defaults
to the name of the class. Its name can be changed using the name element into
@Entity.
@Entity(name = “student”)
Entity classes must not be declared final since JPA implementations try to subclass the
entity in order to provide their functionality.
@Id
The primary key uniquely identifies the instances of the entity. The primary key is a
must for each JPA entity. The @Id annotation is used to define the primary key in a
JPA entity. Identifiers are generated using @GeneratedValue annotation. There are
four strategies to generate id. The strategy element in @GeneratedValue can have
value from any of AUTO, TABLE, SEQUENCE, or IDENTITY.
@Entity
public class Student
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
privateintid;
@Table
Bydefault, the name of the table in the database will be the same as the entity name.
@Table annotation is used to define the name of the table in the database.
@Entity
7
Configuration of @Table(name="STUDENT")
Hibernate (ORM)
publicclass Student
{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
privateintid;
@Column
Similar to @Table annotation, @Column annotation is used to provide the details of
columns into the database. Check the other elements defined into @Column, such as
length, nullable, unique.
@Entity
@Table(name="STUDENT")
publicclass Student
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
privateintid;
@Transient
@Transient annotation is used to make a field into an entity as non-persistent. For
example, the age of a student can be calculated from the date of birth. Thus, age field
can be made as non-persistent into Student class as shown below-
@Entity
@Table(name=”STUDENT”)
publicclass Student
8
@Id Spring Boot and Hibernate
(ORM)
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = “id”)
privateintid;
@Transient
privateintage;
}
@Temporal
The types in the java.sql package such as java.sql.Date, java.sql.Time,
java.sql.Timestamp are in line with SQL data types. Thus, its mapping is
straightforward, and either the @basic or @column annotation can be used. The type
java.util.Date contains both date and time information. This is not directly related to
any SQL data type. For this reason, another annotation is required to specify the
desired SQL type. @Temporal annotation is used to specify the desired SQL data
type. It has a single element TemporalType. TemporalType can be DATE, TIME or
TIMESTAMP. The type of java.util.Calendar also requires @Temporal annotation
to map with the corresponding SQL data type.
@Entity
@Table(name="STUDENT")
publicclass Student
{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
privateintid;
@Column(name = "firstname", length=50, nullable=false, unique=false)
private String firstName;
@Column(name = "lastname", length=50, nullable=true, unique=false)
private String lastName;
@Transient
privateintage;
@Temporal(TemporalType.DATE)
@Column(name = "dateofbirth", nullable = false)
private Date dob;
}
The types from the java.time package in Java 8is directly mapped to corresponding
SQL types. So there's no need to explicitly specify @Temporal annotation:
• LocalDate is mapped to DATE
9
Configuration of
• Instant, LocalDateTime, OffsetDateTime and ZonedDateTime are mapped
Hibernate (ORM) to TIMESTAMP
• LocalTime and OffsetTime are mapped to TIME
This section explains all steps required to create Hibernate Application with Mysql
using Java configuration without using hibernate.cfg.xml. In the application, the Data
Access Object (DAO) layer persists the Student entity and retrieves the persisted
entity from the database. Required tools and technologies are as follows:
• IDE – Eclipse
• Hibernate 5.3.7.Final
• Maven
• MySQL 8
• JavaSE 1.8
Perform the following steps to create and run the Hibernate Application.
Step 1: Maven project is created into Eclipse IDE. The directory structure of the
project with various layers is shown below-
<dependencies>
<!‐‐ https://mvnrepository.com/artifact/mysql/mysql‐connector‐java ‐‐>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql‐connector‐java</artifactId>
<version>8.0.13</version>
</dependency>
<!‐‐ https://mvnrepository.com/artifact/org.hibernate/hibernate‐core ‐
‐>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate‐core</artifactId>
<version>5.3.7.Final</version>
10
</dependency> Spring Boot and Hibernate
<dependency> (ORM)
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind‐api</artifactId>
<version>2.3.2</version>
</dependency>
</dependencies>
publicclassHibernateUtil
{
privatestaticSessionFactorysessionFactory;
publicstaticSessionFactorygetSessionFactory()
{
if (sessionFactory == null)
{
try
{
Configuration configuration = newConfiguration();
// Hibernate settings equivalent to hibernate.cfg.xml's properties
Properties settings = newProperties();
settings.put(Environment.DRIVER, "com.mysql.cj.jdbc.Driver");
settings.put(Environment.URL,
"jdbc:mysql://localhost:3306/test?useSSL=false");
settings.put(Environment.USER, "root");
settings.put(Environment.PASS, "root");
settings.put(Environment.DIALECT,
"org.hibernate.dialect.MySQL5Dialect");
settings.put(Environment.SHOW_SQL, "true");
settings.put(Environment.CURRENT_SESSION_CONTEXT_CLASS, "thread");
settings.put(Environment.HBM2DDL_AUTO, "create‐drop");
configuration.setProperties(settings);
configuration.addAnnotatedClass(Student.class);
ServiceRegistryserviceRegistry = newStandardServiceRegistryBuilder()
.applySettings(configuration.getProperties()).build();
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
}
catch (Exception e)
{
e.printStackTrace();
}
}
returnsessionFactory;
}
}
Step 4: Create a JPA Entity/Persistent class. This example creates the Student
persistent class, which is mapped to a student database table. A Persistent class should
follow some rules:
• Prefer non-final class: Hibernate uses proxies to apply some performance
optimization. JPA entity or Hibernate Persistent class as final limits the ability
of hibernate to use proxies. Without proxies, the application loses lazy loading
which will cost performance.
• A no-arg constructor: Hibernate creates an instance of a persistent class
using newInstance() method. Thus, a persistent class should have a default
constructor at least package visibility.
• Identifier Property: Each JPA entity should have a Primary Key. Thus an
attribute should be annotated with @Id annotation.
• Getter and Setter methods: Hibernate recognizes the method by getter and
setter method names by default.
/**
* @authorRahulSingh
*/
@Entity
@Table(name="student")
publicclass Student
{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
privateintid;
@Column(name = "firstname", length=50, nullable=false, unique=false)
private String firstName;
@Column(name = "lastname", length=50, nullable=true, unique=false)
private String lastName;
@Transient
privateintage;
@Temporal(TemporalType.DATE)
@Column(name = "dateofbirth", nullable = false)
private Date dob;
private String email;
publicStudent()
{
}
publicStudent(String firstName, String lastName, String email, Date dob)
{
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
this.dob = dob;
}
publicintgetId()
{
returnid;
}
publicvoidsetId(intid)
{
this.id = id;
}
public String getFirstName()
{
returnfirstName;
}
publicvoidsetFirstName(String firstName)
{
this.firstName = firstName;
}
public String getLastName()
{
returnlastName;
12
} Spring Boot and Hibernate
publicvoidsetLastName(String lastName) (ORM)
{
this.lastName = lastName;
}
public String getEmail()
{
returnemail;
}
publicvoidsetEmail(String email)
{
this.email = email;
}
publicintgetAge()
{
returnage;
}
publicvoidsetAge(intage)
{
this.age = age;
}
public Date getDob()
{
return dob;
}
publicvoidsetDob(Date dob)
{
this.dob = dob;
}
@Override
public String toString()
{
return"Student [id=" + id + ", firstName=" + firstName + ", lastName=" + lastName + ", age=" + age + ", dob="
+ dob + ", email=" + email + "]";
}
}
Step 5: Create a DAO layer that performs the operations to the database. StudentDao
code is given below, which performs two operations.
• save(Student student) – saves a given Student into the database.
• getStudentList() – retrieves all students from the database.
publicclassStudentDao
publicvoidsave(Student student)
catch (Exception e)
13
Configuration of
Hibernate (ORM) if (txn != null)
txn.rollback();
e.printStackTrace();
public List<Student>getStudentList()
{
try (Session sess = HibernateUtil.getSessionFactory().openSession())
{
returnsess.createQuery("from Student", Student.class).list();
}
}
Step 7: Run the application from eclipse IDE or command line. Check the logs in the
console and record into the database. The application is executed with eclipse IDE. It
saves student records into a database. Console log with insert and select query
generated by Hibernate as shown below:
14
Spring Boot and Hibernate
Output (ORM)
This section describes the persistence context. It also explains how hibernate uses the
concept of persistence context to solve the problem of managing the entities at
runtime.
The persistence context sits between the application and database store. Persistence
context keeps monitoring the managed entity and marks the entity as dirty if some
modification has been done during a transaction. Persistence context can be
considered as a staging area or first-level cache where all the loaded and saved objects
to the database reside during a session.
1. Transient
2. Persistent
3. Detached
4. Removed
15
Configuuration of Transient: An object off a POJO class is in a transsient state when created ussing a new
Hibernaate (ORM)
F
Figure 10.4: Hiibernate Entitty Lifecycle Sttates
operator in Java. In the ttransient statee, the object is not relatedd to any databbase table.
An object in i a transiennt state is nott managed bby session orr Entity Mannager. The
transient staate object is not
n tracked foor any modification from the t persistencce context.
Thus, any modification
m oof a transient state
s object does
d not impacct the databasse.
Persistent: When a Traansient entity is saved, it iis associated with a uniquue session
object and it
i enters into a Persistent state.
s A Persiistent state enntity is a repreesentation
of a row intto a databasee, although thhe row might not exist in the database yet; upon
flushing thee session, thee entity is gu
uaranteed to have
h a corresponding row w into the
database. Session
S manaages the Perssistent state objects and keeps track of every
modificationn done. Sesssion propaggates all the modificatioons into the database
automatically. The Hibbernate sessio on’s followinng methods make an enntity into
Persistent sttate.
• sesssion.save()
• sesssion.update()
• sesssion.saveOrU Update()
• sesssion.lock()
• sesssion.merge()
publicclassPersiistentStateExamplle
{
publicstaticvoidmain(String[] args)
{
Transactionn txn = null;
try (Sessionn sess = HibernateeUtil.getSessionFactory().openSessioon())
{
ttxn = sess.beginTrransaction(); // starrt a transaction
SSimpleDateFormaatdateFormat = new wSimpleDateForm mat("dd-MM-yyyyy");
D
Date dob = dateFoormat.parse("10-099-1995");
SStudent student = newStudent("Rahuul", "", "[email protected]", doob); // 1
ssess.saveOrUpdatee(student); // 2
LList<Student>studdents = sess.createQ Query("from Studdent", Student.classs).list();
sstudents.forEach(ss ->System.out.priintln(s)); // 3
sstudent.setLastNam me("Singh"); //4
sstudents = sess.creeateQuery("from S Student",Student.cllass).list();
sstudents.forEach(ss ->System.out.priintln(s)); //5
ttxn.commit(); // 6
}
catch (Exceeption e)
16
{ Spring Boot and Hibernate
if (txn != null) (ORM)
{
txn.rollback();
}
e.printStackTrace();
}
}
}
Output:
publicclassDetachedStateExample
{
publicstaticvoidmain(String[] args)
{
try
{
Session sess = HibernateUtil.getSessionFactory().openSession();
SimpleDateFormatdateFormat = newSimpleDateFormat("dd-MM-yyyy");
Date dob = dateFormat.parse("10-09-1995");
Student student = newStudent("Rahul", "", "[email protected]", dob);
17
Configuration of sess.saveOrUpdate(student); //student entity is in persistent state
Hibernate (ORM) List<Student>students = sess.createQuery("from Student",
Student.class).list();
sess.close(); // session close() makes student entity in detached state.
students.forEach(s ->System.out.println(s));
student.setLastName("Singh"); //This change is not tracked by Hibernate
session.
sess = HibernateUtil.getSessionFactory().openSession();
sess.update(student); // session update() makes the detached object into
persistent state.
students = sess.createQuery("from Student",Student.class).list();
students.forEach(s ->System.out.println(s));
sess.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
Removed: Once a persistent object passes through session’s delete() method, it enters
into Removed state. When an application commits the session the entries in the
database that correspond to remove entities are deleted. At this state, java instance
exists but any change made to the instance will not be saved into the database. If the
removed entities are not referenced anywhere, then it is eligible for garbage
collection.
The following sections explain the various Hibernate operations and differences
between the same types of operations.
publicclassEntityLoadExample
publicstaticvoidmain(String[] args)
{
try
{
18
Session sess = HibernateUtil.getSessionFactory().openSession(); Spring Boot and Hibernate
SimpleDateFormatdateFormat = newSimpleDateFormat("dd-MM-yyyy"); (ORM)
Date dob = dateFormat.parse("10-09-1995");
Student student = newStudent("Rahul", "Singh", "[email protected]", dob);
sess.save(student); //student entity is in persistent state
sess.close();
intstudentId = student.getId(); //Id has been generated and set on call of save method.
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
Session get() method: Theget() method is similar to the load() method to fetch the
entity from the database. Like load() method, get() methods also take an identifier and
either an entity name of a class. Some important overloaded methods are as follows:
• public Object get(Class<T>clazz, Serializable id) throws HibernateException
• public Object get(String entityName, Serializable id) throws
HibernateException
Difference between load() and get() methods
Although load() and get() methods perform the same task, still the differences exist in
their return values in case the identifier does not exist in the database.
• The get() method returns NULL if the identifier does not exist.
• The load() method throws a runtime exception if the identifier does not exist.
19
Configuration of
• A transient state object becomes a persistent object, and the operation
Hibernate (ORM) cascades all of its relation with cascade=PERSIST or cascade=ALL. The spec
does not say that persist() method will generate the Id right away but on
commit or flush,non-null Id is guaranteed. The persist() method does not
promise the Id as non-null just after calling this method. Thus one should not
rely upon it.
• The persist() method has no impact on persistent objects, but the operation
still cascaded all of its relation with cascade=PERSIST or cascade=ALL.
• The persist() method on detached objects throws an exception, either upon
calling this method or upon committing or flushing the session.
A sample example explains the above points with output. For better understanding,
have hands-on with the following code.
publicclassEntityPersistExample
{
publicstaticvoidmain(String[] args)
{
try
{
Session sess = HibernateUtil.getSessionFactory().openSession();
Transaction txn = sess.beginTransaction();
SimpleDateFormatdateFormat = newSimpleDateFormat("dd-MM-yyyy");
Date dob = dateFormat.parse("10-09-1995");
Student student = newStudent("Abhishek", "Singh", "[email protected]", dob);
sess.persist(student); //student entity is transitioned from transit -> persistent
sess.persist(student); // No impact
sess.evict(student); // student entity is transitioned from persistent -> detached
Output:
Session save() method: The save() method is similar to the persist() method which
stores the record into the database. This is the original Hibernate Session method
which does not conform to JPA specification. The save() method differs from the
persist() method in terms of its implementation. The documentation of this method
states that at first, it assigns the generated id to the identifier and then persists the
entity. The save() method returns the Serializable value of this identifier. The
semantics of save() method is as follows:
20
● A transient state object becomes a persistent object and the operation cascades Spring Boot and Hibernate
all of its relation with cascade=PERSIST or cascade=ALL. At first it assigns (ORM)
the generated id to the identifier and then persists the entity.
● The save() method has no impact on persistent objects, but the operation still
cascaded all of its relations with cascade=PERSIST or cascade=ALL.
● The save() method on detached instances creates a new persistent instance. It
assigns the new generated Id to the identifier, which results in a duplicate
record in the database upon committing or flushing.
A sample example explains the above points with output as shown below:
publicclassEntitySaveExample
publicstaticvoidmain(String[] args)
try
SimpleDateFormatdateFormat = newSimpleDateFormat("dd-MM-yyyy");
Integer id1 = (Integer) sess.save(student); //student entity is transitioned from transit ->
persistent
System.out.println("Id1: "+id1);
System.out.println("Id2: "+id2);
System.out.println("Id3: "+id3);
txn.commit();
sess.close();
catch (Exception e)
e.printStackTrace();
}
}
21
Configuration of Execution Result:
Hibernate (ORM)
It can be observed in the above log that the detached instance is saved into the
database with a newly generated id and which results in a duplicate record into the
database as shown in the database screenshot.
Session saveOrUpdate() method: This method either performs save() or update() on
the basis of identifier existence. E.g. If an identifier exists for the instance, update()
method will be called otherwise save() will be performed. The saveOrUpdate()
method handles the cases where we need to save a detached instance. Unlike the
save() operation on detached instances, the saveOrUpdate() method does not result in
a duplicate record. Similar to update(), this method is used to reattach an instance to
the session. This method can be considered as a universal tool to make an object
persistent regardless of its state, whether it is transient or detached.
publicclassEntitySaveOrUpdateExample
{
publicstaticvoidmain(String[] args)
{
try
{
Session sess = HibernateUtil.getSessionFactory().openSession();
Transaction txn = sess.beginTransaction();
SimpleDateFormatdateFormat = newSimpleDateFormat("dd-MM-yyyy");
Date dob = dateFormat.parse("10-09-1995");
Student student = newStudent("Abhishek", "Singh", "[email protected]", dob);
sess.saveOrUpdate(student); //student entity is transitioned from transit -> persistent
System.out.println("Id1: "+student.getId());
sess.saveOrUpdate(student); // No impact
System.out.println("Id2: "+student.getId());
22
} Spring Boot and Hibernate
(ORM)
Program Output:
As in output, you can see that saveOrUpdate() operation does not result in duplicate
records even for the detached entity . Thus, this operation can be used as a universal
tool to make an object persistent regardless of its state.
HQL Update query to update the student’s last name as ‘Singh’ whose id 1.
HQL Insert
In HQL, only the INSERT INTO … SELECT … is supported; there is no INSERT
INTO … VALUES. HQL only support insert from another table. For example, insert
student records from another student_backup table. This is also called bulk-insert
statement.
Java Persistence API (JPA) is just a specification that defines APIs for object-
relational mappings and management of persistent objects. It is a set of interfaces that
can be used to implement the persistence layer. It itself doesn’t provide any
24
implementation classes. In order to use the JPA, a provider is required which Spring Boot and Hibernate
implements the specifications. Hibernate and EclipseLink are popular JPA providers. (ORM)
Spring Data JPA is one of the many sub-projects of Spring Datathat simplifies the
data access for relational data stores. Spring Data JPA is not a JPA provider; instead it
wraps the JPA provider and adds its own features like a no-code implementation of
the repository pattern. Spring Data JPA uses Hibernate as the default JPA provider.
JPA provider is configurable, and other providers can also be used with Spring Data
JPA. Spring Data JPA provides a complete abstraction over the DAO layer into the
project.
Spring Data JPA introduces the concept of JPA Repositories. JPA Repositories are a
set of Interfaces that defines query methods. It does not require writing native queries
anymore. Sometimes custom queries may be required in order to fetch the data from
the database. These queries are JPQL (Java Persistence Query Language), not native
queries. The advantages of using Spring Data JPA are as follows.
Query Methods
Another robust and comfortable feature of Spring Data JPA is the Query Methods.
Based on the name of methods declared in the repository interfaces are converted to
low-level SQL queries at runtime. If the custom query isn’t complex, only a method is
required to be defined in the repository interface with a name starting with find…By.
Here is an example of a Student Repository to find a student by id and list of students
based on firstName and lastName.
public interface StudentRepository extends CrudRepository<Student, Long>
{
Optional<Student>findById(Long studentId);
List<Student>findByFirstNameAndLastName(String firstName, String lastName);
}
1) What is the difference between load() and get() method of Hibernate Session?
25
Configuration of …………………………………………………………………………
Hibernate (ORM)
…………………………………………………………………………
…………………………………………………………………………
…………………………………………………………………………
2) What is the difference between persist() and save() method of Hibernate
Session?
…………………………………………………………………………
…………………………………………………………………………
…………………………………………………………………………
…………………………………………………………………………
3) Why is Hibernate Session's saveOrUpdate() method considered a universal
tool to make an object persistent?
…………………………………………………………………………
…………………………………………………………………………
…………………………………………………………………………
…………………………………………………………………………
4) Explain Spring Data JPA with its advantages.
…………………………………………………………………………
…………………………………………………………………………
…………………………………………………………………………
…………………………………………………………………………
10.6 SUMMARY
This unit has explained the concepts of ORM, Hibernate as ORM tool and Spring
Data JPA, which uses Hibernate as the default JPA provider. Below are the important
things which have been explained.
• Many different data storage technologies are available in this world, and each
one comes with its own data access API and driver.
• ORM stands for Object Relational Mapping, where a Java object is mapped to
a database table and with APIs.We need to work with objects and not with
native queries.
• The Java Persistence API (JPA) is a specification that defines how to persist
data in Java applications
• The Hibernate architecture elements includ such as SessionFactory, Session,
Query, First Level Cache and Second Level Cache. The first level cache can’t
be disabled.
• In order to use optimized performance of Hibernate, a POJO should follow
some rules such as-
o Prefer non-final class
o A no-arg constructor
o Identifier property
o Getter and Setter method
• The Hibernate entity lifecycle states as transient, persistent, detached and
removed.
26
• The Hibernate Session persist(), and the save() methods perform the same job Spring Boot and Hibernate
still; their implementation differs in terms of generated Id assignment. (ORM)
• The saveOrUpdate() method can be used as a universal tool for persisting an
entity irrespective of entity state.
• Spring Data JPA takes one step forward and enables developers to use data
access layers without any implementation.
27
Configuration of A Transaction represents a unit of work with the database, and most of the
Hibernate (ORM) RDBMS supports transaction functionality. Transaction object provides
methods for transaction management. Transaction objects enable data
consistency, and rollback in case something goes wrong.
28
3) Hibernate works with POJO. Without any Hibernate specific annotation and Spring Boot and Hibernate
mapping, Hibernate does not recognize these POJOs. Once properly annotated (ORM)
with required annotation, hibernate identifies them and keeps track of them to
perform database operations such as create, read, update and delete. These
POJOs are considered as mapped with Hibernate. An instance of a class
mapped with Hibernate, can be any of the four persistence states which are
known as hibernate entity lifecycle states.
Same as Figure 10.5: Hibernate Entity Lifecycle States
1. Transient
2. Persistent
3. Detached
4. Removed
• The get() method returns NULL if the identifier does not exist.
• The load() method throws a runtime exception if the identifier does
not exist.
2) Differences between save() and persist() methods are listedin the below table.
2 Transaction It can save object within boundaries It can only save object within
Boundaries and outside boundaries the transaction boundaries
3 Return It returns generated id and return It does not return anything. Its
Type type is serializable return type is void.
29
Configuration of
Hibernate (ORM) 4 Detached It will create a new row in the table It will throw persistence
Object for detached object exception for detached object
4) Spring Data JPA is one of the many sub-projects of Spring Data which
simplifies the data access for relational data stores. Spring Data JPA is not a
JPA provider; instead it wraps the JPA provider and adds its own features like
a no-code implementation of the repository pattern. Spring Data JPA uses
Hibernate as the default JPA provider. JPA provider is configurable, and other
providers can also be used with Spring Data JPA. Spring Data JPA provides
complete abstraction over the DAO layer into the project. The advantages of
using Spring Data JPA are as follows:
30
● Christian Bauer, Gavin King, and Gary Gregory, “Java Persistence with Spring Boot and Hibernate
(ORM)
Hibernate”,Manning Publications, 2015.
● Ethan Marcotte, “Responsive Web Design”, Jeffrey Zeldman Publication,
2011(http://nadin.miem.edu.ru/images_2015/responsive-web-design-2nd-
edition.pdf)
● Tomcy John, “Hands-On Spring Security 5 for Reactive Applications”,Packt
Publishing,2018
● https://docs.jboss.org/hibernate/orm/3.5/reference/en/html/tutorial.html
● https://www.w3spoint.com/get-vs-load-hibernate
● https://www.baeldung.com/learn-jpa-hibernate
● https://www.javatpoint.com/hibernate-with-annotation
● https://www.tutorialspoint.com/jpa/index.htm
● https://howtodoinjava.com/hibernate/hibernate-jpa-2-persistence-annotations-
tutorial/
● https://docs.jboss.org/hibernate/orm/3.6/quickstart/en-US/html/hibernate-gsg-
tutorial-jpa.html
● https://www.baeldung.com/hibernate-save-persist-update-merge-saveorupdate
● https://www.journaldev.com/3472/hibernate-session-get-vs-load-difference-
with-examples
● https://www.baeldung.com/the-persistence-layer-with-spring-data-jpa
● https://dzone.com/articles/spring-data-jpa
31
UNIT 11 CRUD APPLICATION USING
SPRING BOOT AND HIBERNATE
11.0 INTRODUCTION
Nowadays, there are varieties of data stores such as relational databases, NoSQL
databases like MongoDB, Casandraetc, Big Data solutions such as Hadoop etc.
Different storage technologies have different configurations, different methods and
different API's to fetch the data.
Spring Data simplifies and makes homogeneous data access technologies for
relational and non-relational databases, cloud-based data services and map-reduce
frameworks. Spring Data provides an abstraction that allows us to connect in the same
way to relational databases and NoSQL databases. Thus, switching can be done
effortlessly between data stores.
Spring Data JPA is one of the many sub-projects of Spring Datathat focuses on
simplification of the data access for relational data stores. It is not a JPA provider;
instead, it wraps the JPA provider and adds its own features like a no-code
implementation of the repository pattern. Hibernate is the default JPA provider into
Spring Data JPA. Spring Data JPA is very flexible, and other providers can also be
configured as JPA providers. Spring Data JPA provides a complete abstraction over
the DAO layer into the project.
The actual strength of Spring Data JPA lies in the repository abstraction. The
repository abstraction enables us to write the business logic code on a higher
abstraction level. Developers do not need to worry about DAO layer
implementations;instead they just need to learn Spring Data repository interfaces.
Crud Application Using Spring Data provides an implementation for these repository interfaces out-of-the-
Spring Boot and Hibernate box.
The Hibernate mappings are one of the key features of Hibernate. Association in
Hibernate tells the relationship between the objects of POJO classes, i.e. how the
entities are related to each other. The established relationship can be either
unidirectional or bidirectional. The supported relationships are similar to the database
relationships such as One-to-One, Many-to-Many, Many-to-One/One-to-Many.
11.1 OBJECTIVES
The previous unit gave us the overview of Spring Data JPA. This section explains the
Spring Data Repository to create the persistence layer into the Spring Boot
application.
The Spring Data repository aims to reduce the boilerplate code required to implement
the DAO layer into a project for various persistence stores. Spring Data repository has
different interfaces, each having different functionality. Thefollowing interfaces in the
Spring Data repository have been explained.
• CrudRepository
• PagingAndSortingRepository
• JpaRepository
JpaRepository extends PagingAndSortingRepository interface, which extends
CrudRepository. Thus, JpaRepository contains all API of CrudRepositoty and
PagingAndSortingRepository. The persistent layer can extend any of the above
interfaces based on required APIs. The implementation of persistent layers is very
easy and is shown asan example.
@Entity
publicclass Book
{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
privateintid;
The Spring Data Repository will auto-generate the implementation based on the
method name. Supported keywords inside method name can be found at -
https://docs.spring.io/spring-data/data-jpa/docs/current/reference/html/#jpa.query-
methods.query-creation
11.2.1 CrudRepository
This interface provides all basic CRUD operation related APIs. The methods provided
in CrudRepository are shown in the code.
publicinterfaceCrudRepository<T, ID>extends Repository<T, ID>
{
Optional<T>findById(ID id);
booleanexistsById(IDid);
Iterable<T>findAll();
Iterable<T>findAllById(Iterable<ID>ids);
long count();
voiddeleteById(ID id);
voiddeleteAll();
}
3
Crud Application Using 11.2.2 PagingAndSortingRepository
Spring Boot and Hibernate
PagingAndSortingRepository interface extends CrudRepository interface. It provides
the paging and sorting feature apart from CRUD feature. The methods in the interface
are shown in the code.
publicinterfacePagingAndSortingRepository<T, ID>extendsCrudRepository<T, ID>
{
Iterable<T>findAll(Sort sort);
Page<T>findAll(Pageablepageable);
}
11.2.3 JpaRepository
@Override
List<T>findAll();
@Override
List<T>findAll(Sort sort);
@Override
List<T>findAllById(Iterable<ID>ids);
@Override
<S extends T> List<S>saveAll(Iterable<S>entities);
void flush();
voiddeleteInBatch(Iterable<T>entities);
voiddeleteAllInBatch();
T getOne(ID id);
@Override
<S extends T> List<S>findAll(Example<S>example);
@Override
<S extends T> List<S>findAll(Example<S>example, Sort sort);
}
4
Check Your Progress 1: Spring Boot and Hibernate
(ORM)
1) What is the relationship between JPA, Hibernate and Spring data JPA?
The previous unit has explained that hibernate can identify POJO classes as persistent
only when they are annotated with certain annotations. While making the POJO
classes as persistent entities using JPA annotations, we may face situations where two
entities can be related and must be referenced from each other, either uni-directional
or bi-directional. Association mappings are one of the key features of JPA
and Hibernate. That establishes the relationship between two database tables as
attributes in your model and allows you to easily navigate the association in your
model and JPQL or criteria queries.
When only one pair of entities contains a reference to the other, the association
is unidirectional. If the pair of entities contains a reference to each other, then it is
referred to as bi-directional. Entities can contain references to other entities, either
directly as an embedded property or field or indirectly via a collection of some sort
(arrays, sets, lists, etc.). There is no impact of unidirectional or bidirectional
association on database mapping. Foreign Key Relationships are used to represent
the associations in the underlying tables.
JPA and Hibernate have the same association as you are aware of relational databases.
The followings are the association that will be described in subsequent sections.
• one-to-many/many-to-one
• one-to-one
• many-to-many
5
Crud Application Using 11.3.1 One-to-Many / Many-to-One
Spring Boot and Hibernate
One-to-Many and Many-to-One relationships are the opposite sides of the same coin
and closely related. One-to-Many mapping is described as one row in a table and is
mapped to multiple rows in another table.
For the illustration of the One-to-Many relationship, the Teacher and their Courses
will be taken. A teacher can give multiple courses but a course which is given by only
one teacher is an example of one-to-many relationship. While another perspective,
many courses are given by a teacher, is an example of the many-to-one relationship.
Before diving into details of how to map this relationship, let’s create the entities.
@Entity
publicclass Teacher
{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
}
@Entity
publicclass Course
{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
privateintid;
private String title;
}
Now, the Teacher class should include a list of courses, and mapping will be required
to map this relationship into the database. This will be annotated with a @OnetoMany
annotation.
@Entity
publicclass Teacher
{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToMany(cascade = CascadeType.ALL)
private List<Course>courses;
}
With the above configuration, Hibernate uses an association table to map the
relationship. With the above configuration, three tables named teacher, course and
teacher_courses will be created. But, definitely, we are not looking for such mapping.
In order to avoid the third table teacher_courses, @JoinColumn annotation is used to
specify the foreign key column.
6
@Entity Spring Boot and Hibernate
publicclass Teacher (ORM)
{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToMany(cascade = CascadeType.ALL)
@JoinColumn(name = "teacher_id", referencedColumnName = "id")
private List<Course>courses;
}
The tables created into the database and save() operation on teacher object will result
in the following into the database (as shown in Figure 11.1, 11.2 and 11.3):
The previous example has defined the Teacher class as the owning side of the One-to-
Many relationship. This is because the Teacher class defines the join column between
the two tables. The Course is called the referencing side in the relationship.
Course class can be made as to the owning side of the relationship by mapping the
Teacher field with @ManytoOne in the course class instead.
@Entity
publicclass Teacher
{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
}
@Entity
publicclassCourse
{
@Id
7
Crud Application Using @GeneratedValue(strategy = GenerationType.IDENTITY)
Spring Boot and Hibernate privateintid;
private String title;
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "teacher_id", referencedColumnName = "id")
private Teacher teacher;
}
Teacher.java
packagecom.ignou.hibernate.association.learning.entity;
@Entity
publicclass Teacher
{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
8
FetchType.EAGER)
Spring Boot and Hibernate
private List<Course>courses;
(ORM)
public Teacher() {}
publicvoidsetId(Long id)
{
this.id = id;
}
publicvoidsetName(String name)
{
this.name = name;
}
public List<Course>getCourses()
{
returncourses;
}
publicvoidsetCourses(List<Course>courses)
{
this.courses = courses;
}
@Override
public String toString()
{
return"Teacher [id=" + id + ", name=" + name + ", courses=" + courses + "]";
}
}
The Teacher class has reference courses. Teacher and Course has a relationship as
one-to-many, and thus, it is annotated with @OnetoMany. @OnetoManyannotation
has an attribute mappedBy. Without mappedBy attribute, we would not have a two-
way relationship. The mappedBy attributes indicatesthe JPA that the field is already
mapped by another entity. It's mapped by the teacher field of the Course entity. Other
attributes such as cascade and fetch will be explained in the next section.
Course.java
packagecom.ignou.hibernate.association.learning.entity;
@Entity
publicclass Course
{
9
Crud Application Using @Id
Spring Boot and Hibernate @GeneratedValue(strategy = GenerationType.IDENTITY)
privateintid;
private String title;
@ManyToOne
@JoinColumn(name = "teacher_id", referencedColumnName = "id")
private Teacher teacher;
public Course()
{
}
public Course(String title)
{
this.title = title;
}
publicintgetId()
{
returnid;
}
publicvoidsetId(intid)
{
this.id = id;
}
public String getTitle()
{
returntitle;
}
publicvoidsetTitle(String title)
{
this.title = title;
}
public Teacher getTeacher()
{
returnteacher;
}
publicvoidsetTeacher(Teacher teacher)
{
this.teacher = teacher;
}
@Override
public String toString()
{
return"Course [id=" + id + ", title=" + title + "]";
}
}
TeacherRepository.java
packagecom.ignou.hibernate.association.learning.repository;
publicinterfaceTeacherRepositoryextendsCrudRepository<Teacher, Long>
{
// No code repository. Spring data JPA will provide the implementation.
}
10
CourseRepository.java Spring Boot and Hibernate
(ORM)
packagecom.ignou.hibernate.association.learning.repository;
publicinterfaceCourseRepositoryextendsCrudRepository<Course, Long>
{
// No code repository. Spring data JPA will provide the implementation.
}
SpringHibernateJpaApplication.java
packagecom.ignou.hibernate.association.learning;
@SpringBootApplication
publicclassSpringHibernateJpaApplicationimplementsCommandLineRunner
{
@Autowired
privateTeacherRepositoryteacherRepo;
@Override
publicvoidrun(String... args) throws Exception
{
Teacher t1 = new Teacher("Vijay Kumar");
List<Course>courseList = newArrayList<Course>();
courseList.add(c1);
courseList.add(c2);
t1.setCourses(courseList);
c1.setTeacher(t1);
c2.setTeacher(t1);
t1 = teacherRepo.save(t1);
Teacher t = teacherRepo.findById(t1.getId()).get();
System.out.println(t);
}
}
It is worth noting that a mapped relationship should not impact the software’s memory
by putting too many unnecessary entities. For example, consider that the Course is a
heavy object, i.e. having too many attributes. For some business logic, all Teacher
objects are loaded from the database. Business logic does not need to retrieve or use
courses in it but Course objects are still being loaded alongside the Teacher objects.
Such loading will degrade the performance of applications. Technically, this can be
solved by using the Data Transfer Object Design Pattern and
retrieving Teacher information without the courses.
JPA has considered all such problems ahead and made One-to-Many relationships
load lazily by default. Lazy loading means relationships will be loaded when it is
11
Crud Application Using actually needed. The execution of @OnetoMany relationship with the default fetch
Spring Boot and Hibernate type will issue two queries. First is for the Teacher object and the second for the
Course objects when it’s needed. The log of the query issued by Hibernate is as
follows.
While the execution of @OnetoMany relationship with fetch type as Eager will issue
only one query, Log of the query issued by Hibernate is as follows.
@ManyToOne(fetch = FetchType.LAZY)
private Teacher teacher;
JPA operations affect the only entity on which it has been performed. These
operations will not affect the other entities that are related to it. For example, In case
of Person-Address relationship, the Address entity doesn’t have any meaning of its
own without a Person entity. Thus, on delete of Person entity, Address entity should
also get deleted.
Cascading is about JPA actions involving one entity propagating to other entities via
an association. JPA provides javax.persistence.CascadeType enumerated types that
define the cascade operations. These cascading operations can be defined with any
type of mapping i.e. One-to-One, One-to-Many, Many-to-One, Many-to-Many. JPA
provides the following cascade type to perform cascading operations.
12
Spring Boot and Hibernate
(ORM)
Cascade Type Description
ALL CascadeType.ALL propagates all operations including hibernate
specific from a parent to a child entity.
PERSIST CascadeType.PERSIST propagates the save() or persist() operation to
the related entities.
MERGE CascadeType.MERGE propagates only the merge() operation to the
related entities.
REFRESH CascadeType.REFRESH propagates only the refresh() operation to the
related entities.
REMOVE CascadeType.REMOVE removes all related entities association when
the owning entity is deleted.
DETACH CascadeType.DETACH detaches all related entities if owning entity is
detached.
Hibernate provides three additional Cascade Types along with provided by JPA.
Hibernate provides org.hibernate.annotations.CascadeTypeenumerated types that
define the cascade operations.
• CascadeType.REPLICATE
• CascadeType.SAVE_UPDATE
• CascadeType.Lock
11.3.2 One-to-One
One-to-One mapping is described as one row in a table mapped to only one row in
another table.
For the illustration of One-to-One relationship, The Student and the Address have
been taken.
ER diagram of foreign key based one-to-one mapping is shown in Figure 11.5. The
address_id column in Student is the foreign key to the address.
Figure 11.5: ER Diagram For One-to-One Mapping With Foreign Key
@Entity
publicclass Student
{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
13
Crud Application Using private Long id;
Spring Boot and Hibernate
private String name;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name="address_id", referencedColumnName = "id")
private Address address;
// getter setter
}
The Student and the Address has a one-to-one relationship. Entity Student comprises
another entity Address, and it is annotated with @OnetoOne annotation. Check the
cascade attribute into the annotation. Student entity is the owner, and thus, it has
@JoinColumn annotation on Address entity. @JoinColumn is to configure the name
of the column in the Student table that maps to the primary key in the address table. If
the name attribute is not provided in @JoinColumn, Hibernate will follow some rules
to select the default name of the column.
@Entity
publicclass Address
{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
privateintid;
private String street;
private String state;
private String pincode;
private String country;
@OneToOne(mappedBy = "address")
private Student student;
// getter setter
The Address entity is having @OneToOne annotation on another entity Student with
attribute mappedBy. The mappedBy attribute is used since the Address is non-owning.
Note that on both entities @OneToOne annotations are used since its bidirectional.
In this strategy, instead of creating a new column address_id, we'll mark the
primary key column (student_id) of the address table as the foreign key to
the student table. ER diagram is shown in Figure 11.6. This strategy optimizes the
storage space.
Figure 11.6: ER Diagram For One-to-One Mapping With Shared Primary Key
14
Spring Boot and Hibernate
(ORM)
@Entity
publicclass Student
{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
// getter setter
}
publicclass Address
@Id
@Column(name ="student_id")
privateintid;
@OneToOne
@MapsId
@JoinColumn(name="student_id")
// getter setter
15
Crud Application Using The identifier of the Address entity is still having @Id annotation but it no longer uses
Spring Boot and Hibernate @GeneratedValue annotation. Instead it references the student_id column. The
@MapsIdindicates that the primary key values will be copied from the Student entity.
11.3.3 Many-to-Many
For the illustration of Many-to-Many relationship, Book and the Author have been
taken. A book may be written by multiple writers and a writer will write multiple
books. Thus, the Book and Author relationship is many-to-many and is shown as an
ER diagram in Figure 11.7.
The JPA implementation for many-to-many mapping for Book as owning side is
shown below:
@Entity
@Table(name = "books")
publicclass Book
{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
//Other fields
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "book_author" , joinColumns = @JoinColumn(name =
"book_id" ), inverseJoinColumns = @JoinColumn(name = "author_id"))
private List<Author>authors;
//getter setter
@Column(name = "author_name")
@Size(max = 100)
@NotNull
private String name;
2) Explain Eager and Lazy loading in Hibernate. How does it improve the
performance of hibernate applications?
17
Crud Application Using The previous unit explained Spring Data JPA and hibernate as the default provider
Spring Boot and Hibernate for Spring Data JPA. This unit has elaborated on Spring Data Repository and
hibernate association mapping. This section provides the complete Rest Application to
create records using Spring Boot and Hibernate by using all the explained concepts.
The example considers the many-to-many relationship between Book and Author.
Many books can be written by an Author and many authors can write a book. The
same example will be considered for CRUD operation.The required tools and
software are as follows:
• Eclipse IDE
• Maven
• Spring Boot
• Hibernate
• Mysql
• Postman
Visit Spring Initializr (https://start.spring.io) in order to generate the spring project
(shown in Figure 11.8). Add the required dependencies and export the project into
eclipse as maven project. Modify the data source properties into application.properties
file and do some hands-on.
Figure11.8: SpringBoot Project Setup Using Spring Initializr
18
Spring Boot and Hibernate
(ORM)
@Override
publicvoid run(String... args) throws Exception
{
Book b1 = new Book("Java In Action", "ISBN-001");
List<Book>bookList = newArrayList<Book>();
bookList.add(b1);
List<Author>authorList = newArrayList<Author>();
authorList.add(au1);
authorList.add(au2);
b1.setAuthors(authorList);
au1.setBooks(bookList);
au2.setBooks(bookList);
bookRepository.save(b1);
19
Crud Application Using Book b2 = new Book("Java 8 In Action", "ISBN-002");
Spring Boot and Hibernate List<Book>bookList2 = newArrayList<Book>();
bookList2.add(b2);
List<Author>authorList2 = newArrayList<Author>();
authorList2.add(au3);
authorList2.add(au4);
b2.setAuthors(authorList2);
au3.setBooks(bookList2);
au4.setBooks(bookList2);
bookRepository.save(b2);
}
}
@RestController
@RequestMapping("/books")
publicclassBookController
{
@Autowired
privateBookRepositorybookRepository;
@Autowired
privateAuthorRepositoryauthorRepository;
@PostMapping
public Book createBookRecord(@Valid@RequestBody Book b)
{
returnbookRepository.save(b);
}
}
In the example, there are two entities Book and Author, having a many-to-many
relationship. Entities with bidirectional many-to-many associations are shown in the
code.
Book.java
@Entity
@Table(name = "books")
publicclass Book
{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
20
private Long id;
Spring Boot and Hibernate
(ORM)
@NotNull
@Size(max=75)
private String title;
@NotNull
@Size(max = 100)
private String isbn;
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(joinColumns = @JoinColumn(name = "book_id" ), inverseJoinColumns
= @JoinColumn(name = "author_id"))
private List<Author>authors;
public Book() {}
// getter setter
@Override
public String toString()
{
return"Book [id=" + id + ", title=" + title + ", isbn=" + isbn + ", authors=" + authors
+ "]";
}
}
Author.java
@Entity
@Table(name = "authors")
publicclass Author
{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "author_name")
@Size(max = 100)
@NotNull
private String name;
public Author() {}
21
Crud Application Using super();
Spring Boot and Hibernate this.name = name;
}
// getter setter
@Override
public String toString()
{
return"Author [id=" + id + ", name=" + name + ", rating=" + rating + "]";
}
}
@Repository
publicinterfaceBookRepositoryextendsCrudRepository<Book, Long>
{
// No implementation is required.
}
application.properties
# DATASOURCE (DataSourceAutoConfiguration&DataSourceProperties)
spring.datasource.url=jdbc:mysql://localhost:3306/test?useSSL=false&serverTimezone=UTC
&useLegacyDatetimeCode=false
spring.datasource.username=root
spring.datasource.password=root
# Hibernate
# The SQL dialect makes Hibernate generate better SQL for the chosen database
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type=TRACE
spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true
22
Spring Boot and Hibernate
(ORM)
23
Crud Application Using 3. Spring Data JPA also provides a Like keyword, but it behaves differently. An
Spring Boot and Hibernate example to call the findByTitle(…) is shown inBookRepository code in the
next paragraph.
4. Sometimes we need to create queries that are too complicated for Query
Methods or would result in absurdly long method names. In those cases, we
can use the @Query annotation to query our database.
• Named Parameters (:name) – Query parameters can be passed as
named parameters into the query. Check the example in the
aboveBookRepository.
• Ordinal Parameters (?index) - JPQL also supports ordinal parameters,
whose form is ?index. An example of ordinal parameters is as
“Select b from Book b where b.title like %?1%”
24
BookController.java Spring Boot and Hibernate
(ORM)
@RestController
@RequestMapping("/books")
publicclassBookController
@Autowired
privateBookRepositorybookRepository;
@GetMapping
publicIterable<Book>getBooks()
returnbookRepository.findAll();
@GetMapping("/search-by-method-containing")
returnbookRepository.findByTitleContaining(pattern);
@GetMapping("/search-by-method-like")
returnbookRepository.findByTitleLike("%"+pattern+"%");
@GetMapping("/search-by-query")
returnbookRepository.findByTitle(pattern);
}
}
The BookController provides the following GET endpoints to get all books and
search the book with title keywords.
25
Crud Application Using • http://localhost:8080/books - Returns all the books with its authors.
Spring Boot and Hibernate • http://localhost:8080/search-by-method-containing?q=Java – Returns all the
books with title containing Java
• http://localhost:8080/search-by-method-like?q=Java – Returns all the books
with title containing Java.
• http://localhost:8080/search-by-query?q=Java – Returns all the books with
title containing Java
BookController.java
@RestController
@RequestMapping("/books")
publicclassBookController
{
@Autowired
privateBookRepositorybookRepository;
@PutMapping
public Book updateBook(@Valid@RequestBody Book b)
{
returnbookRepository.save(b);
}
To test the update feature, use the postman and use the PUT method with a valid Book
record into the request body. Following request, update the authors of the given book
with id 3 (as shown in Figure 11.11).
26
11.7 DELETE RECORDS USING SPRING BOOT Spring Boot and Hibernate
(ORM)
AND HIBERNATE
@RestController
@RequestMapping("/books")
publicclassBookController
{
@Autowired
privateBookRepositorybookRepository;
@DeleteMapping("/{bookId}")
@ResponseStatus(value = HttpStatus.OK)
publicvoiddeleteBook(@PathVariable(value="bookId", required=true) Long bookId)
{
bookRepository.deleteById(bookId);
}
}
BookController.java
The delete operation does not return any body response. It just returns the response
status as 200 OK on successful deletion. Use the postman to issue the DELETE
request, as shown into the screenshot (Figure 11.12). Thefollowing is the delete
request to delete the book with id as 2. The response status is 200 OK, and the
response body is empty as expected.
27
Crud Application Using
Spring Boot and Hibernate
2) How does Spring Data framework derive queries from method names?
28
Spring Boot and Hibernate
(ORM)
11.8 SUMMARY
This unit has explained Spring Data Repository with a complete example using other
hibernate association concepts. For better understanding, start coding by using the
examples explained in this unit. The important points are as following:
• The goal of Spring Data repository abstraction is to significantly reduce the
amount of boilerplate code required to implement data access layers for
various persistence stores.
• CrudRepository, PagingAndSortingRepository and JpaRepositoryhave been
explained with all available methods.
• Association mappings are one of the key features of JPA and Hibernate. That
establishes the relationship between two database tables as attributes in your
model and allows you to navigate the association easily in your model and
JPQL or criteria queries
• JPA has considered the related entity loading overhead problems ahead and
made One-to-Many relationships load lazily by default.
• The fetch type for Many-to-One relationship is eager by default.
• Cascading is about JPA actions involving one entity propagating to other
entities via an association. JPA provides javax.persistence.CascadeType
enumerated types that define the cascade operations. JPA provides the
cascade types as ALL, PERSIST, MERGE, REFRESH, REMOVE,
DETACH.
• Query methods using Containing, Contains, and IsContaining generate the
like query. For example, query method findByTitleContaining(String pattern)
generates the sql query as SELECT * FROM books WHERE title LIKE
'%<pattern>%'
• Query parameters as Named Parameters (:name) and Ordinal Parameters
(?index)
29
Crud Application Using features like a no-code implementation of the repository pattern. Spring Data
Spring Boot and Hibernate JPA uses Hibernate as the default JPA provider.
3) CrudRepository provides all the typical Save, Update, Delete operations for
an entity while JpaRepository extends CrudRepository as well as Repository,
QueryByExampleExecutor and PagingAndSortingRepository interfaces.
So, if only CRUD operations are required to perform, select
CRUDRepository. Else, if one or more features out of Pagination, Batch
processing and flush operations are required, choose JPARepository.
Check Your Progress 2
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToMany(cascade = CascadeType.ALL)
@JoinColumn(name = "teacher_id", referencedColumnName = "id")
private List<Course>courses;
}
@Entity
publicclass Course
{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
privateintid;
private String title;
}
30
2) The difference between lazy and eager loading is described in the table. Spring Boot and Hibernate
(ORM)
S.No Key Lazy Eager
.
1 Fetching In Lazy loading, associated In Eager loading, data
strategy data loads only when we loading happens at the time
explicitly call getter or size of their parent is fetched
method.
2 Default ManyToMany and ManyToOne and OneToOne
Strategy in OneToMany associations associations used a lazy
ORM Layers used a lazy loading loading strategy by default.
strategy by default.
3 Loading It can be enabled by using It can be enabled by using
Configuration the annotation parameter : the annotation parameter :
3) One of the main aspects of JPA is that it helps to propagate Parent to Child
relationships. This behavior is possible through CascadeTypes. The
CascadeTypes supported by JPA are:
Cascade Description
Type
ALL CascadeType.ALL propagates all operations, including hibernate
specific from a parent to a child entity.
PERSIST CascadeType.PERSIST propagates the save() or persist() operation
to the related entities.
MERGE CascadeType.MERGE propagates only the merge() operation to the
related entities.
REFRESH CascadeType.REFRESH propagates only the refresh() operation to
the related entities.
REMOVE CascadeType.REMOVE removes all related entities associations
when the owning entity is deleted.
DETACH CascadeType.DETACH detaches all related entities if the owning
entity is detached.
31
Crud Application Using Cascading is useful only for Parent - Child associations where the parent
Spring Boot and Hibernate entity state transitions cascade to the child entity. The cascade configuration
option accepts an array of CascadeTypes. The below example shows how to
add the refresh and merge operations in the cascade operations for a One-to-
Many relationship:
@OneToMany(cascade={CascadeType.REFRESH, CascadeType.MERGE},
fetch = FetchType.LAZY)
@JoinColumn(name="EMPLOYEE_ID")
private Set<AccountEntity> accounts;
Now only when the save() or persist() methods are called using an employee
instance, the accounts will be persisted. If any other method is called on
session, its effect will not affect/cascade to the accounts entity.
2) Spring Data framework has an in-built query builder mechanism that derives
queries based on the method name. Method names are defined as 'find...By..',
'count...By...' etc. 'By' acts as the delimiter to identify the start of the criteria.
'And' and 'Or' are used to define multiple criteria. 'OrderBy' is used to identify
the order by criteria. Few examples of query methods are as follows:
• findByFirstname(String firstName): It derives the query to get the
list based on the first name.
• findByFirstnameAndLastname(String firstName, String
lastName): It derives the query to get the list based on first name and
last name
• findByFirstnameAndLastnameOrderByFirstnameAcs(String
firstName, string last): it derives the query to get the list based on
the first name and sorted by the first name in ascending order.
33