Spring 4 MVC Hibernate JPA Java Config Tutorial
Spring 4 MVC Hibernate JPA Java Config Tutorial helps developers who are looking for spring java based configuration to initiate MVC and database application context. In this spring mvc jpa example, we will see customer CRUD operations, where it displays list of customers, add and edit customer.
If you are looking for XML bases example for this same, please visit below tutorial:
Spring 4 MVC Hibernate JPA XML Config Example
Spring 4 MVC Hibernate JPA XML Config Example helps developers who are looking for spring XML based configuration to initiate MVC and root application context. READ MORE
Installations:
- Eclipse
- Tomcat 8
- Spring 4
- Spring ORM and Transaction Management
- Hibernate 5
- Bootstrap
- MVC
- Maven
As shown in the below, This tutorial is more like Spring MVC CRUD with transactions with below functionalities:
- Displaying Customer List
- Adding new customer
- Editing customer
- Deleting customer.
Spring 4 MVC Hibernate CRUD Example:
- Lets create a maven project with below details: In Eclipse, click File -> New -> Project -> Maven -> Maven Project
- Select simple maven project and click on Next
- Give below details and click on Finish
- Lets create the below project structure and we will follow recommended standards in creating layers:
- org.javasavvy.demo.app.config: This package contains root application context such as database config, services etc
- org.javasavvy.demo.web.config : It contans web mvc dispatcher servlet config and web application intializer as we are not using web.xml file
- org.javasavvy.demo.ui.controller : It contains controllers
- org.javasavvy.demo.dao : Data access layer that inject EntityManager
- org.javasavvy.demo.services : Service Layer classes
- org.javasavvy.demo.entity: Contains JPA Entities
- As this is maven project, you need to update pom.xml file with dependencies.Please click here to download pom.xml
Application Java Configuration Initialization:
- In this tutorial, We will not use web.xml. Spring provides WebApplicationInitializer interface, detects the class automatically and intializes Dispatcher Servlet.
- AbstractDispatcherServletInitializer class is abstract class and implementation of WebApplicationInitializer makes easy to register the DispatcherServlet by simply overriding methods to specify the servlet mapping and the location of the DispatcherServlet
- Create WebAppinitializer class which is replacement of web.xml like shown below:
- In this, register DatabaseConfig and WebMVCConfig to AnnotationConfigWebApplicationContext class.
-
public class CustomerWebAppIntializer implements WebApplicationInitializer { public void onStartup(ServletContext container) throws ServletException { AnnotationConfigWebApplicationContext webContext = new AnnotationConfigWebApplicationContext(); webContext.register(DatabaseConfig.class); webContext.register(CustomerWebMVCConfig.class); webContext.setServletContext(container); ServletRegistration.Dynamic reg=container.addServlet("dispatcherServlet", new DispatcherServlet(webContext)); reg.setLoadOnStartup(1); reg.addMapping("*.action"); } }
-
Spring MVC Java Config Class:
- Spring MVC Configuration required for distacher servlet to create handlers, controllers and view resolvers.
- . Lets create CustomerWebMVCConfig class to configures that need to annotate with @Configuration,@EnableMVC :
- View Resolver : Create ViewResolver bean
- Static View Paths via ViewControllerRegistry: This is equivalant to <mvc:view-controller /> annotations to register view with controllers directly
- Cotroller Component Scan : In this set basePackages to MVC Controller packages and it will scan the packages and create controller bean automatically
-
@Configuration @EnableWebMvc @ComponentScan(basePackages={"org.javasavvy.demo.ui.controller"}) public class CustomerWebMVCConfig extends WebMvcConfigurerAdapter { @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/").setViewName("home"); registry.addViewController("/home.action").setViewName("home"); registry.addViewController("/customer/customerForm.action").setViewName("addCustomer"); } @Bean public ViewResolver viewResolver() { InternalResourceViewResolver viewResolver = new InternalResourceViewResolver(); viewResolver.setViewClass(JstlView.class); viewResolver.setPrefix("/WEB-INF/views/"); viewResolver.setSuffix(".jsp"); return viewResolver; } }
App and Database Java config :
- This is root application context which need to register with AnnotationConfigWebApplicationContext class to load beans
- @ComponentScan : Set services and dao layer packages path to basePackages attribute. It scans these folder and creates bean which are annotated with @Component,@Service,@Repository
Spring JPA and Transaction Configuration:
- spring JPA configuration is available in org.springframework.orm.jpa library which you need to add dependency
- JPA requires EntityManager to perform data base operations. In Spring, you can get the EntityManager below ways:
- LocalEntityManagerFactoryBean: This is suitable for simple applications that uses JPA for Data access only. It requires persistence unit name only. you can not use the existing data source and no support for global transactions
- LocalContainerEntityManagerFactoryBean : It gives full control and most powerful JPA setup option, allows for flexible local configuration within the application. This allows you to customize below :
- persistance unit name
- entity packages path to scan
- existing Data Source
- JPA properties
- you can set local and global transaction
Spring Transaction Managers:
- @EnableTransactionManagement is equivalent to <tx:annotation-driven/> and looks for @Transaction classes and enables declarative transaction.
- JtaTransactionManager: is appropriate for handling distributed transactions, where transactions that spans multiple resources, and for controlling transactions on application server resources. Mostly you will use this for JNDI data source
- DataSourceTransactionManager is appropriate for a single JDBCDataSource or Spring JDBC
- HibernateTransactionManager is appropriate for accessing a single resource with Hibernate SessionFactory
- JpaTransactionManager is appropriate for applications that uses EntityManagerFactory and provides belowcapabilities
- local JDBC transactions such as transaction-specific isolation levels
- resource-level read-only optimizations against regular JDBC connection pool
- It also supports direct DataSource access within transaction
- JpaTransctionManager need to configure with JPA Provider to make transactions. In this example, we set JPA Provider which HibernateJPAProvider to EnityManagerFactoryBean. Spring supports out of the box dialects for the EclipseLink, Hibernate and OpenJPA JPA implementations
-
@Configuration @ComponentScan(basePackages={"org.javasavvy.demo.services","org.javasavvy.demo.dao"}) @EnableTransactionManagement public class DatabaseConfig { @Bean public DriverManagerDataSource getDataSource() { DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://localhost:3306/javasavvy"); dataSource.setUsername("root"); dataSource.setPassword("root"); return dataSource; } @Bean @Autowired public PlatformTransactionManager getTransactionManager(EntityManagerFactory emf) throws NamingException{ JpaTransactionManager jpaTransaction = new JpaTransactionManager(); jpaTransaction.setEntityManagerFactory(emf); return jpaTransaction; } @Bean public LocalContainerEntityManagerFactoryBean getEMF() { LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean(); emf.setDataSource(getDataSource()); emf.setPersistenceUnitName("spring-jpa-unit"); emf.setJpaVendorAdapter(getHibernateAdapter()); Properties jpaProperties = new Properties(); jpaProperties.put("hibernate.dialect", "org.hibernate.dialect.MySQLDialect"); jpaProperties.put("hibernate.hbm2ddl.auto", "update"); jpaProperties.put("hibernate.show_sql", "true"); jpaProperties.put("hibernate.format_sql","false"); emf.setJpaProperties(jpaProperties); return emf; } @Bean public JpaVendorAdapter getHibernateAdapter() { return new HibernateJpaVendorAdapter(); } }
Data Access Layer Configuration:
- Lets create a entity customer and map the customer entry persistence.xml file in src/main/resource/META-INF folder.
-
@Entity @Table(name="customer") public class Customer { @Id @GeneratedValue(strategy=GenerationType.AUTO) private long customerId; private String customerName; private String country; @Temporal(TemporalType.TIMESTAMP) private Date createdDate; @Temporal(TemporalType.TIMESTAMP) private Date updateDate;
- Create persistence.xml in src/main/resource/META-INF folder and create persitence unit name “spring-jpa-unit” which need to map to EntityManagerFactory bean
-
<?xml version="1.0" encoding="UTF-8"?> <persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> <persistence-unit name="spring-jpa-unit"> <class>org.javasavvy.demo.entity.Customer</class> </persistence-unit> </persistence>
-
- Create CustomerDAO Interface that exposes below methods
-
public interface CustomerDAO { public Customer addCustomer(Customer customer); public Customer updateCustomer(Customer customer); public void deleteCustomer(long customerId); public Customer getCustomer(long customerId); public List<Customer> getCustomers(); }
-
- Create CustomerDAOImpl class for CRUD operations on customer entity. This class uses entityManager via @PersistenceContext annotation
-
@Repository("customerDAO") @Transactional public class CustomerDAOImpl implements CustomerDAO{ @PersistenceContext public EntityManager entityManager; @Transactional(readOnly=false) public Customer addCustomer(Customer customer) { entityManager.persist(customer); return customer; } @Transactional(readOnly=false) public Customer updateCustomer(Customer customer) { entityManager.merge(customer); return customer; } @Transactional(readOnly=false) public void deleteCustomer(long customerId) { // delete code goes here } @Transactional(readOnly=true) public Customer getCustomer(long customerId) { String sql = "select customer from Customer customer where customer.customerId="+customerId; try{ return (Customer) entityManager.createQuery(sql).getSingleResult(); }catch(Exception e){ } return null; } @Transactional(readOnly=true) public List<Customer> getCustomers() { return entityManager.createQuery("select customer from Customer customer").getResultList(); } }
-
Service Layer:
Lets create Service Layer that uses CustomerDAO classes
- Customer Service Interface:
-
public interface CustomerService { public Customer addCustomer(String customerName, String country); public Customer updateCustomer(long customerId,String customerName, String country); public Customer getCustomer(long customerId); public List<Customer> getAllCustomers(); }
-
- CustomerServiceImpl: annotate CustomerServiceImpl class wtih @Service(“customerService”), provide the bean name also here to avoid autowire dependency issues.
- @Transactional annotatation will creates new transction if not exists
-
@Service("customerService") @Transactional public class CustomerServiceImpl implements CustomerService { @Autowired(required=true) @Qualifier("customerDAO") private CustomerDAO customerDAO; @Transactional public Customer addCustomer(String customerName, String country) { System.out.println("Cusomer Service create invoked:"+customerName); Customer customer = new Customer(); customer.setCountry(country); customer.setCustomerName(customerName); customer.setCreatedDate(new Date()); customer.setUpdateDate(new Date()); customer = customerDAO.addCustomer(customer); return customer; } @Transactional public Customer updateCustomer(long customerId,String customerName, String country) { System.out.println("Cusomer Service Update invoked:"+customerName); Customer customer = new Customer(); customer.setCustomerId(customerId); customer.setCountry(country); customer.setCustomerName(customerName); customer.setUpdateDate(new Date()); customer = customerDAO.updateCustomer(customer); return customer; } public Customer getCustomer(long customerId) { return customerDAO.getCustomer(customerId); } public List<Customer> getAllCustomers() { return customerDAO.getCustomers(); } }
-
MVC Layer:
- Create Controller class that uses CustomerService to access CRUD operations.
header.jsp -
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <c:set var="appPath" value="${pageContext.request.contextPath}"/> <% String contextPath = request.getContextPath(); %> <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link href='<%=contextPath+"/css/bootstrap.min.css" %>' rel="stylesheet"> <link href='<%=contextPath+"/css/font-awesome.min.css" %>' rel="stylesheet"> <link href='<%=contextPath+"/css/customer.css" %>' rel="stylesheet"> </head> <body> <div class="navbar navbar-inverse navbar-fixed-left"> <div class="container-fluid"> <div class="navbar-header"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#myNavbar"> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="#">JavaSavvy</a> </div> <div class="collapse navbar-collapse" id="myNavbar"> <ul class="nav navbar-nav"> <li ><a href="<%=contextPath%>/home.action">Home</a></li> <li><a href="<%=contextPath%>/customer/customers.action">Customers</a></li> <li><a href="#">Page 2</a></li> <li><a href="#">Page 3</a></li> </ul> <ul class="nav navbar-nav navbar-right"> <li><a href="#"><span class="glyphicon glyphicon-user"></span> Sign Up</a></li> <li><a href="#"><span class="glyphicon glyphicon-log-in"></span> Login</a></li> </ul> </div> </div> </div>
- footer.jsp
-
<script src="<%=request.getContextPath() + "/js/jquery-1.11.1.min.js"%>"></script> <script src="<%=request.getContextPath() + "/js/bootstrap.min.js"%>"></script> </body> </html>
-
- customers.jsp
-
<%@ include file="header.jsp" %> <div class="container-fluid"> <div class="row"> <div class="col-md-12"> <div class=""> <a class="btn btn-primary" href="<%=contextPath%>/customer/customerForm.action" style="margin-left:50%;">Add Customer</a> </div> <div class="table-responsive"> <table id="mytable" class="table table-bordered" style="margin:10px;width:60%;"> <thead> <th>Customer Id</th> <th>Customer Name</th> <th>Country</th> <th>Created Date</th> <th>Edit</th> </thead> <tbody> <c:forEach var="customer" items="${customers}"> <tr> <td>${customer.customerId }</td> <td>${customer.customerName }</td> <td>${customer.country }</td> <td>${customer.createdDate }</td> <td> <a class="btn btn-primary" href="<%=contextPath%>/customer/editCustomerView/${customer.customerId}.action">Edit</a> <a class="btn btn-warning" href="<%=contextPath%>/customer/deleteCustomer/customerId=${customer.customerId}.action">Delete</a> </td> </tr> </c:forEach> </tbody> </table> <div class="clearfix"></div> </div> </div> </div> </div> <%@ include file="footer.jsp" %>
-
- add Customer.jsp
-
<%@ include file="header.jsp" %> <div class="container-fluid"> <div class="row"> <div class="col-md-6"> </div> <div class="col-md-6"> <h2>Add Customer</h2> <form class="form-horizontal" action="<%=request.getContextPath()%>/customer/addCustomer.action" method="post" role="form"> <div class="form-group"> <label for="title">Customer Name</label> <div class="input-group"> <span class="input-group-addon"> <span class="glyphicon glyphicon-cog"></span></span> <input type="text" class="form-control" name="name" id="name" placeholder="Enter Name" required> </div> </div> <div class="form-group"> <label for="desc">Country</label> <div class="input-group"> <span class="input-group-addon"> <span class="glyphicon glyphicon-pencil"></span></span> <input type="text" class="form-control" name="country" id="desc" placeholder="Enter Country" required> </div> </div> <button type="submit" class="btn btn-primary">Submit</button> </form> </div> </div> </div>
-
- edit customer.jsp
-
<%@ include file="header.jsp" %> <div class="container-fluid"> <div class="row"> <div class="col-md-6"> </div> <div class="col-md-6"> <h2>Edit Customer: ${customer.customerName }</h2> <form class="form-horizontal" action="<%=request.getContextPath()%>/customer/editCustomer.action" method="post" role="form"> <input type="hidden" value="${customer.customerId }" name="customerId" id="customerId"> <div class="form-group"> <label for="title">Customer Name</label> <div class="input-group"> <span class="input-group-addon"> <span class="glyphicon glyphicon-cog"></span></span> <input type="text" value="${customer.customerName }" class="form-control" name="name" id="name" placeholder="Enter Name" required> </div> </div> <div class="form-group"> <label for="desc">Country</label> <div class="input-group"> <span class="input-group-addon"> <span class="glyphicon glyphicon-pencil"></span></span> <input type="text" class="form-control" name="country" value="${customer.country }" placeholder="Enter Country" required> </div> </div> <button type="submit" class="btn btn-primary">Update</button> </form> </div> </div> </div>
-
- home.jsp
-
<%@ include file="header.jsp" %> <div class="row"> <div class="col-md-12"> This is Home page </div> </div> <%@ include file="footer.jsp" %>
-
- customer.css
-
.navbar-inverse .navbar-nav>li>a { color: white; } .navbar-inverse { background-color: #428bca; border-color: none; }
-
- Please add Jquery and bootstrap files as per below folder structure in webapp directory
Hope this helps.
16 thoughts on “Spring 4 MVC Hibernate JPA Java Config Tutorial”
Comments are closed.
Nice article and very helpful.
Can we create spring mvc porlet in liferay using java config which you mention above?
Thanks,
Krunal
Yes. We can create Spring MVC Portlet as it follows JSR 286 Portlet Specifications.
didn’t work. i’m getting 404
Cannot find link to download source code
Please download from below link:
https://www.javasavvy.com/wp-content/uploads/2017/02/spring-mvc4-jpa.zip
Hi guys! I’m newbie in Spring and I need your help. I receive 404 error when try to run the example under my GF server. May be I missed any config files?
Download source code from below link:
https://www.javasavvy.com/wp-content/uploads/2017/02/spring-mvc4-jpa.zip
Hi Jayaram,
While running this example, getting this error. Can you please help me in this.
The absolute uri: http://java.sun.com/jsp/jstl/core cannot be resolved in either web.xml or the jar files deployed with this application
how to resolve ?
The absolute uri: http://java.sun.com/jsp/jstl/core cannot be resolved in either web.xml or the jar files deployed with this application
I solved the same problem. I’ve just added JSTL-1.2.jar to /apache-tomcat-x.x.x/lib and set scope to provided in maven pom.xml:
jstl
jstl
1.2
provided
Hi,
I have downloaded the code from https://www.javasavvy.com/wp-content/uploads/2017/02/spring-mvc4-jpa.zip and build the war using maven and was even able to successfully deploy the war file in liferay 7 CE GA5 version, but when i added the portlet to a portal page i am getting a empty page and no errors are displayed on the eclipse console, not sure what is going on did anyone face the same issue.
Program throw error 500: org.apache.jasper.JasperException: The absolute uri: http://java.sun.com/jsp/jstl/core cannot be resolved in either web.xml or the jar files deployed with this application
I added jstl-1.2.jar using pom.xml but still showing error.
why not use xml ?
a professional project is done with xml or java configuration
Hi, when I run the program, I’m having the problem below
Message: /index.jsp (line: [1], column: [1]) The absolute uri: [http://java.sun.com/jsp/jstl/core] cannot be resolved in either web.xml or the jar files deployed with this application
Description: The server encountered an unexpected condition that prevented it from fulfilling the request.
I have a Problem….
Estado HTTP 500 – Internal Server Error
Tipo Informe de Excepción
mensaje /index.jsp (línea: [1], columna: [1]) La uri absoluta: [http://java.sun.com/jsp/jstl/core] no puede resolverse o en web.xml o el los archivos jar desplegados con esta aplicación
descripción El servidor encontró un error interno que hizo que no pudiera rellenar este requerimiento.
excepción
org.apache.jasper.JasperException: /index.jsp (línea: [1], columna: [1]) La uri absoluta: [http://java.sun.com/jsp/jstl/core] no puede resolverse o en web.xml o el los archivos jar desplegados con esta aplicación
org.apache.jasper.compiler.DefaultErrorHandler.jspError(DefaultErrorHandler.java:42)
org.apache.jasper.compiler.ErrorDispatcher.dispatch(ErrorDispatcher.java:292)
org.apache.jasper.compiler.ErrorDispatcher.jspError(ErrorDispatcher.java:98)
org.apache.jasper.compiler.Parser.processIncludeDirective(Parser.java:347)
org.apache.jasper.compiler.Parser.parseIncludeDirective(Parser.java:380)
org.apache.jasper.compiler.Parser.parseDirective(Parser.java:481)
org.apache.jasper.compiler.Parser.parseElements(Parser.java:1445)
org.apache.jasper.compiler.Parser.parse(Parser.java:144)
org.apache.jasper.compiler.ParserController.doParse(ParserController.java:244)
org.apache.jasper.compiler.ParserController.parse(ParserController.java:105)
org.apache.jasper.compiler.Compiler.generateJava(Compiler.java:206)
org.apache.jasper.compiler.Compiler.compile(Compiler.java:385)
org.apache.jasper.compiler.Compiler.compile(Compiler.java:362)
org.apache.jasper.compiler.Compiler.compile(Compiler.java:346)
org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:603)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:400)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:386)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:330)
javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
nota La traza completa de la causa de este error se encuentra en los archivos de diario del servidor.
Pivotal tc Runtime 9.0.13.B.RELEASE
Please Help Me
I am getting 404 error on click of any button like Home or Customer. its annoying