Spring vs Hibernate Example
1. Introduction
In this post, we feature a comprehensive Example on Spring vs Hibernate. This is an in-depth article related to differences between the Spring application framework and Hibernate framework. Spring Framework helps in creating stand-alone and production-ready applications. Spring Framework features are Spring MVC, JPA, Spring Boot, Micro Containers and Messaging. In this article, we look at Spring Boot based application. Hibernate framework has packages related to ORM, Search , Validator and JPA support for NoSql databases. We look at Hibernate ORM application to see the differences from Spring Boot application.
2. Spring vs Hibernate Example
2.1 Prerequisites
Java 7 or 8 is required on the linux, windows or mac operating system. Maven 3.6.1 is required for building the spring and hibernate application.
2.2 Download
You can download Java 8 can be downloaded from the Oracle web site . Apache Maven 3.6.1 can be downloaded from Apache site. Spring framework latest releases are available from the spring website. Hibernate Framework releases are found at this link. H2 database releases are found from H2 database site.
2.3 Setup
You can set the environment variables for JAVA_HOME and PATH. They can be set as shown below:
Java Environment
JAVA_HOME=”/jboss/jdk1.8.0_73″ export JAVA_HOME PATH=$JAVA_HOME/bin:$PATH export PATH
The environment variables for maven are set as below:
Maven Environment
JAVA_HOME=”/jboss/jdk1.8.0_73″ export M2_HOME=/users/bhagvan.kommadi/Desktop/apache-maven-3.6.1 export M2=$M2_HOME/bin export PATH=$M2:$PATH
2.4 Building the Application
2.4.1 Spring
You can start building Spring applications using Spring Boot. Spring Boot has minimal configuration of Spring. Spring Boot has simplified security, tracing, application health management and runtime support for webservers. Spring configuration is done through maven pom.xml. The xml configuration is shown as below:
Spring Configuration
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.springframework</groupId> <artifactId>spring-helloworld</artifactId> <version>0.1.0</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.4.RELEASE</version> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <properties> <java.version>1.8</java.version> </properties> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
You can create a HelloWorldController
class as the web controller. The class is annotated using @RestController
. Rest Controller is used to handle requests in Spring Model View Controller framework. Annotation @RequestMapping
is used to annotate the index()
method. The code for the HelloWorldController
class is shown below:
HelloWorldController
package helloworld; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RequestMapping; @RestController public class HelloWorldController { @RequestMapping("/") public String index() { return "Hello World\n"; } }
HelloWorldApp
is created as the Spring Boot web application. When the application starts, beans, and settings are wired up dynamically. They are applied to the application context. The code for HelloWorldApp
class is shown below:
HelloWorldApp
package helloworld; import java.util.Arrays; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ApplicationContext; @SpringBootApplication public class HelloWorldApp { public static void main(String[] args) { ApplicationContext ctx = SpringApplication.run(HelloWorldApp.class, args); System.out.println("Inspecting the beans"); String[] beans = ctx.getBeanDefinitionNames(); Arrays.sort(beans); for (String name : beans) { System.out.println("Bean Name" +name); } } }
Maven is used for building the application. The command below builds the application.
Maven Build Command
mvn package
The output of the executed command is shown below.
The jar file spring-helloworld-0.1.0.jar is created. The following command is used for executing the jar file.
Java Command
java -jar target/spring-helloworld-0.1.0.jar
The output of the Java command is shown as below:
Curl command is invoked on the command line for the execution of index
method. The method returns a String “Hello World” text. @RestController
aggregates the two annotations @Controller
and @ResponseBody
. This results in returning data. The ouput is shown as below.
2.4.2 Hibernate
A developer uses Hibernate ORM framework to add, save and select entities data from the relational database. The ORM framework is based on the Plain Old Java Object and the JavaBean programming model. Hibernate configuration file has the mapping between object to relational. A Message
class is mapped to a MESSAGES table. The configuration xml file is shown below:
Message.hbm.xml
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="org.hibernate.java"> <class name="Message" table="MESSAGES"> <id name="id" column="MESSAGE_ID"> <generator class="increment"/> </id> <property name="date" type="timestamp" column="MESSAGE_DATE"/> <property name="title"/> </class> </hibernate-mapping>
Message
Class has properties such as id
, date
and title
. The property id
is of Long type. Title
property is of the string type. date
Property is of the Date type. The implementation of the Message
Class is shown below:
Message Class
package org.hibernate.java; import java.util.Date; public class Message { private Long id; private String title; private Date date; public Message() { } public Message(String title, Date date) { this.title = title; this.date = date; } public Long getId() { return id; } private void setId(Long id) { this.id = id; } public Date getDate() { return date; } public void setDate(Date date) { this.date = date; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } }
Hibernate configuration XML has the data source related information. The data source configured is h2 in-memory database. Data Source credentials are set in the configuration file. ORM mapping information is configured in this configuration file. The configuration XML file is shown below:
Hibernate Configuration XML
<?xml version='1.0' encoding='utf-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <property name="connection.driver_class">org.h2.Driver</property> <property name="connection.url">jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1;MVCC=TRUE</property> <property name="connection.username">sa</property> <property name="connection.password"/> <property name="connection.pool_size">1</property> <property name="dialect">org.hibernate.dialect.H2Dialect</property> <property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property> <property name="show_sql">true</property> <property name="hbm2ddl.auto">create</property> <mapping resource="org/hibernate/java/Message.hbm.xml"/> </session-factory> </hibernate-configuration>
JavaHibernateApp
application is a java class which has init
, release
, getSessionFactory
methods. SessionFactory
is instantiated. A new session is created to add two messages to the table. After the addition, the session is closed. Another session is opened for selecting the messages from the table. The implementation of the JavaHibernateApp
class is shown below.
JavaHibernateApp Class
package org.hibernate.java; import java.util.Date; import java.util.List; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.boot.MetadataSources; import org.hibernate.boot.registry.StandardServiceRegistry; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; public class JavaHibernateApp { private SessionFactory sessionFactory; public void init() throws Exception { final StandardServiceRegistry registry = new StandardServiceRegistryBuilder() .configure() .build(); try { sessionFactory = new MetadataSources( registry ).buildMetadata().buildSessionFactory(); } catch (Exception e) { e.printStackTrace(); StandardServiceRegistryBuilder.destroy( registry ); } } public void release() throws Exception { if ( sessionFactory != null ) { sessionFactory.close(); } } public SessionFactory getSessionFactory() { return this.sessionFactory; } public static void main(String[] args) { JavaHibernateApp app = new JavaHibernateApp(); try { app.init(); } catch(Exception exception) { exception.printStackTrace(); } SessionFactory sessionFactory = app.getSessionFactory(); Session session = sessionFactory.openSession(); session.beginTransaction(); session.save( new Message( " first Message!", new Date() ) ); session.save( new Message( "second Message", new Date() ) ); session.getTransaction().commit(); session.close(); session = sessionFactory.openSession(); session.beginTransaction(); List result = session.createQuery( "from Message" ).list(); for ( Message message : (List) result ) { System.out.println( "Message (" + message.getDate() + ") : " + message.getTitle() ); } session.getTransaction().commit(); session.close(); try { app.release(); } catch(Exception exception) { exception.printStackTrace(); } } }
The application is built using maven. The maven configuration file is presented below.
Maven Configuration XML
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>hibernate</groupId> <artifactId>hibernate-java</artifactId> <version>5.4.2.Final</version> <packaging>pom</packaging> <name>Hibernate Helloworld</name> <description> an example </description> <properties> <maven.deploy.skip>true</maven.deploy.skip> </properties> <modules> <module>basic</module> </modules> <dependencies> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>5.4.2.Final</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> <version>1.7.5</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <version>1.4.196</version> </dependency> </dependencies> <build> <sourceDirectory>/Users/bhagvan.kommadi/desktop/javacodegeeks/Code/springvshibernate/hibernate/basic/src</sourceDirectory> <scriptSourceDirectory>/Users/bhagvan.kommadi/desktop/javacodegeeks/Code/springvshibernate/hibernate/basic/src/org/hibernate/java</scriptSourceDirectory> <resources> <resource> <directory>/Users/bhagvan.kommadi/desktop/javacodegeeks/Code/springvshibernate/hibernate/basic/src/resources</directory> </resource> <resource> <directory>/Users/bhagvan.kommadi/desktop/javacodegeeks/Code/springvshibernate/hibernate/basic/src</directory> </resource> </resources> <outputDirectory>/Users/bhagvan.kommadi/desktop/javacodegeeks/Code/springvshibernate/hibernate/basic/target/classes</outputDirectory> <directory>/Users/bhagvan.kommadi/desktop/javacodegeeks/Code/springvshibernate/hibernate/basic/target</directory> <finalName>hibernate-java</finalName> <pluginManagement> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> </plugin> <plugin> <artifactId>maven-dependency-plugin</artifactId> </plugin> <plugin> <artifactId>maven-deploy-plugin</artifactId> </plugin> <plugin> <artifactId>maven-jar-plugin</artifactId> </plugin> <plugin> <artifactId>maven-assembly-plugin</artifactId> <configuration> <archive> <manifest> <mainClass>org.hibernate.java.JavaHibernateApp</mainClass> </manifest> </archive> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> </configuration> </plugin> </plugins> </pluginManagement> <testResources> <testResource> <filtering>false</filtering> <directory>src/test/java</directory> <includes> <include>**/*.xml</include> </includes> </testResource> <testResource> <directory>src/test/resources</directory> </testResource> </testResources> </build> </project>
The maven command to build hibernate application is presented below.
Maven Build Command
mvn clean compile assembly:single
The output of the executed maven command is shown below.
The command below executes the built jar file – hibernate-java-jar-with-dependencies.jar.
Java Command
java -jar basic/target/hibernate-java-jar-with-dependencies.jar
The output of the executed command is shown below.
2.5 Unit Tests
2.5.1 Spring
In Spring, MockMvc
is used to send HTTP requests to the DispatcherServlet
. The assertions are made based on the result obtained from the servlet. @AutoConfigureMockMvc
annotation is used with @SpringBootTest
to inject a MockMvc
instance. The implementation of the Spring Unit Test is shown as below:
HelloWorldControllerTest
package helloworld; import static org.hamcrest.Matchers.equalTo; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.http.MediaType; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; @RunWith(SpringRunner.class) @SpringBootTest @AutoConfigureMockMvc public class HelloWorldControllerTest { @Autowired private MockMvc mvc; @Test public void getMessage() throws Exception { mvc.perform(MockMvcRequestBuilders.get("/").accept(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) .andExpect(content().string(equalTo("Hello World\n"))); } }
Maven command is used to run the unit test. The command is as below :
Maven Build Command
mvn package
The output of the executed command is shown below.
2.5.2 Hibernate
JUnit is used for Hibernate application unit testing. JavaApiTest
class has setUp
and tearDown
methods. A SessionFactory
is created at the start-up of the application in setUp
method. The session Factory is used to open a session and close a session. The session factory is closed at the end of the app lifecycle in tearDown
method. JavaApiTest
class implementation is shown below:
JavaApiTest class
package org.hibernate.java; import java.util.Date; import java.util.List; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.boot.MetadataSources; import org.hibernate.boot.registry.StandardServiceRegistry; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import junit.framework.TestCase; public class JavaApiTest extends TestCase { private SessionFactory sessionFactory; @Override protected void setUp() throws Exception { final StandardServiceRegistry registry = new StandardServiceRegistryBuilder() .configure() .build(); try { sessionFactory = new MetadataSources( registry ).buildMetadata().buildSessionFactory(); } catch (Exception e) { StandardServiceRegistryBuilder.destroy( registry ); } } @Override protected void tearDown() throws Exception { if ( sessionFactory != null ) { sessionFactory.close(); } } @SuppressWarnings("unchecked") public void testBasicUsage() { Session session = sessionFactory.openSession(); session.beginTransaction(); session.save( new Message( " first Message!", new Date() ) ); session.save( new Message( "second Message", new Date() ) ); session.getTransaction().commit(); session.close(); session = sessionFactory.openSession(); session.beginTransaction(); List result = session.createQuery( "from Message" ).list(); for ( Message message : (List) result ) { System.out.println( "Message (" + message.getDate() + ") : " + message.getTitle() ); } session.getTransaction().commit(); session.close(); } }
Maven command builds the hibernate application and runs the unit test. The command is shown below:
Maven Command
mvn package
The output of the executed command is shown below.
2.6 Best Practices
In spring framework, the developer can implement custom annotation by implementing ConstraintValidator
. Custom Annotations help in enhancing the separation of concerns. The developer can use a declarative way of implementing custom validators. You can use annotations like AutoWired
and Resource
in spring framework classes. Hibernate provides different query classes. The developer can pick the right query class based on the context. Bind Parameters are used to map the parameters to the right types. The developer can analyze the queries and optimize them for performance.
2.7 Error Handling
Spring framework has features to handle exceptions and errors. Errors in REST APIs help in presenting the issues to the clients. Hibernate framework has SQLExceptionConverter
which can be used for changing the SQLExceptions to JDBCException
hierarchy of Hibernate.
2.8 Performance
Spring framework has features like extending the AbstractMonitoringInterceptor class to log the start, end, and duration of a method. Spring AOP helps in defining and writing code which can intercept the execution of the methods for monitoring the performance. Hibernate framework provides API for the execution of batch multiple SQL statements. This API helps in saving the database roundtrips and reducing the response time.
2.9 Scalability
Spring framework has MVC, ORM, Messaging and Caching support which is very important for scalability. For scalable deployments, developers and architects need to ensure the servers are stateless or implement sticky sessions with load balancers. Caching helps in reducing the load on the database. Hibernate Framework has an API to handle multitenant data. API provides capabilities to handle integration complexities related to multiple data sources. The developer can define a tenant identifier for opening a session. Hibernate can be deployed in an application server cluster and achieve scalability. Hibernate deployment scales well in in-house and on the cloud scenarios.
2.10 Reliability
Spring Boot has a reliable application development framework. SpringBoot applications are deployed as self-contained units using the profiles feature. Hibernate framework provides stability and quality for production-ready deployment.
2.11 Extensibility
Hibernate framework has features for ORM, configuration management, logging which are highly configurable and extensible.
2.12 Security
Spring Security for User interfaces and HTTP back ends is based on Servlet Filters. The spring framework provides support for implementing access rules to methods. Spring Security framework has an architecture which is designed to support both authentication and authorization. Hibernate framework has features for declarative security. The framework allows the methods to be authorized using JACC and JAAS. These features are implemented in the session facade layer.
2.13 Logging
Spring Framework uses Commons Logging for application logging. Different configurations for logging are provided in the framework. They are Java Util Logging, Log4J2, and Logback. Loggers are pre-configured for printing the output on the console or in the configured file. Hibernate framework has support for Log4j through appender features. The appender logs the information such as statement execution time, JDBC batching information and database connection monitoring metrics.
2.14 Management
Spring management features help in configuring a custom port, management server and SSL configuration management. Spring Boot Actuator configures the enabled HTTP endpoints. Spring framework provides management endpoints which are JMX MBeans. Hibernate has management functionality to gather statistics. The developer needs to set the hibernate.generate_statistics configuration property to true. Automated schema migration tools such as Flyway, Liquibase help in migration. The features supported for migration are related to database-specific DDL feature. DDL Features are Rules, Triggers, and Partitioned Tables. The migration scripts are maintained in the Version Control System, with the source code.
2.15 Deployment
The Spring Server supports deployment of applications packaged in the formats such as Raw OSGi Bundles, Java EE WAR, Web Bundles, PAR and Plans. Hibernate can be configured as Stateless Session Service or Bean, JMX service and JCA connector.
3. Download the Source Code
You can download the full source code of this example here: Spring vs Hibernate Example
it’s like comparing apples to bananas, what you just put here has nothing in common, usually when you use the word “vs” it’s about two things that want to solve the same solution.