spring

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.

Spring vs Hibernate - Maven Command
Maven Command – Spring

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:

Spring vs Hibernate - Hello World Beans
Spring Hello World Beans

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.

Spring vs Hibernate - Curl Command
Curl Command – Spring

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.

Spring vs Hibernate - Maven Command
Maven Command – Hibernate

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.

Spring vs Hibernate - Hibernate App
Hibernate App

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.

Spring Unit Test

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.

Hibernate Unit Test

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

Download
You can download the full source code of this example here: Spring vs Hibernate Example

Bhagvan Kommadi

Bhagvan Kommadi is the Founder of Architect Corner & has around 20 years’ experience in the industry, ranging from large scale enterprise development to helping incubate software product start-ups. He has done Masters in Industrial Systems Engineering at Georgia Institute of Technology (1997) and Bachelors in Aerospace Engineering from Indian Institute of Technology, Madras (1993). He is member of IFX forum,Oracle JCP and participant in Java Community Process. He founded Quantica Computacao, the first quantum computing startup in India. Markets and Markets have positioned Quantica Computacao in ‘Emerging Companies’ section of Quantum Computing quadrants. Bhagvan has engineered and developed simulators and tools in the area of quantum technology using IBM Q, Microsoft Q# and Google QScript. He has reviewed the Manning book titled : "Machine Learning with TensorFlow”. He is also the author of Packt Publishing book - "Hands-On Data Structures and Algorithms with Go".He is member of IFX forum,Oracle JCP and participant in Java Community Process. He is member of the MIT Technology Review Global Panel.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

1 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
George
George
4 years ago

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.

Back to top button