Spring-Data
Development of web-applications with the help of Spring MVC implies creation of several logical layers of architecture. One of the layers is a DAO (Repository) layer. It is responsible for communication with a database. If you developed the DAO layer at least once, you should know that it involves a lot of boilerplate code. A Spring Data take a part of the routine job related to the DAO on itself.

In the post I’m going to provide an example of application which will demonstrate Spring Data (JPA) in conjunction with Spring MVC, MySQL and Maven. Hibernate will be used as implementation of the JPA. As you probably know, I’m a real fan of java based configurations, so I will use this approach to configure the Spring Data. In the end of the tutorial you can find a link to the sample project on GitHub.

Preparation

In the article I want to concentrate on the Spring Data, so all stuff which is out topic I will omit. But in the start I want provide a bulk of links which can be helpful for you in context of this tutorial.

These links should give answers on 90% of questions which can occur during reading the post. Let’s start with table creation in the MySQL:

CREATE TABLE `shops` (
  `id` int(6) NOT NULL AUTO_INCREMENT,
  `name` varchar(60) NOT NULL,
  `employees_number` int(6) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;

Now we can go ahead with a java code:

@Entity
@Table(name = "shops")
public class Shop {

	@Id
	@GeneratedValue
	private Integer id;

	private String name;

	@Column(name = "employees_number")
	private Integer emplNumber;

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Integer getEmplNumber() {
		return emplNumber;
	}

	public void setEmplNumber(Integer emplNumber) {
		this.emplNumber = emplNumber;
	}
}

Configuration of Spring Data

I believe that a screenshot of the project will help you to understand what’s going on.

spring-data-jpa-project-structure

In the property file concentrated all configuration data:

#DB properties:
db.driver=com.mysql.jdbc.Driver
db.url=jdbc:mysql://localhost:3306/hibnatedb
db.username=hibuser
db.password=root

#Hibernate Configuration:
hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
hibernate.show_sql=true
entitymanager.packages.to.scan=com.spr.model

The WebAppConfig class contains all java based configurations:

@Configuration
@EnableWebMvc
@EnableTransactionManagement
@ComponentScan("com.spr")
@PropertySource("classpath:application.properties")
@EnableJpaRepositories("com.spr.repository")
public class WebAppConfig {

	private static final String PROPERTY_NAME_DATABASE_DRIVER = "db.driver";
	private static final String PROPERTY_NAME_DATABASE_PASSWORD = "db.password";
	private static final String PROPERTY_NAME_DATABASE_URL = "db.url";
	private static final String PROPERTY_NAME_DATABASE_USERNAME = "db.username";

	private static final String PROPERTY_NAME_HIBERNATE_DIALECT = "hibernate.dialect";
	private static final String PROPERTY_NAME_HIBERNATE_SHOW_SQL = "hibernate.show_sql";
	private static final String PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN = "entitymanager.packages.to.scan";

	@Resource
	private Environment env;

	@Bean
	public DataSource dataSource() {
		DriverManagerDataSource dataSource = new DriverManagerDataSource();

		dataSource.setDriverClassName(env.getRequiredProperty(PROPERTY_NAME_DATABASE_DRIVER));
		dataSource.setUrl(env.getRequiredProperty(PROPERTY_NAME_DATABASE_URL));
		dataSource.setUsername(env.getRequiredProperty(PROPERTY_NAME_DATABASE_USERNAME));
		dataSource.setPassword(env.getRequiredProperty(PROPERTY_NAME_DATABASE_PASSWORD));

		return dataSource;
	}

	@Bean
	public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
		LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
		entityManagerFactoryBean.setDataSource(dataSource());
		entityManagerFactoryBean.setPersistenceProviderClass(HibernatePersistence.class);
		entityManagerFactoryBean.setPackagesToScan(env.getRequiredProperty(PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN));
		
		entityManagerFactoryBean.setJpaProperties(hibProperties());
		
		return entityManagerFactoryBean;
	}

	private Properties hibProperties() {
		Properties properties = new Properties();
		properties.put(PROPERTY_NAME_HIBERNATE_DIALECT,	env.getRequiredProperty(PROPERTY_NAME_HIBERNATE_DIALECT));
		properties.put(PROPERTY_NAME_HIBERNATE_SHOW_SQL, env.getRequiredProperty(PROPERTY_NAME_HIBERNATE_SHOW_SQL));
		return properties;
	}

	@Bean
	public JpaTransactionManager transactionManager() {
		JpaTransactionManager transactionManager = new JpaTransactionManager();
		transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
		return transactionManager;
	}

	@Bean
	public UrlBasedViewResolver setupViewResolver() {
		UrlBasedViewResolver resolver = new UrlBasedViewResolver();
		resolver.setPrefix("/WEB-INF/pages/");
		resolver.setSuffix(".jsp");
		resolver.setViewClass(JstlView.class);
		return resolver;
	}

}

Pay your attention at @EnableJpaRepositories annotation. It enables usage of JPA repositories. The com.spr.repository package will be scaned to detect repositories. In the entityManagerFactory bean I determined that Hibernate will be used as JPA implementation.

Initializer class will be omitted.

DAO & Service layers

The repository for the Shop entity:

package com.spr.repository;

import org.springframework.data.jpa.repository.JpaRepository;

import com.spr.model.Shop;

public interface ShopRepository extends JpaRepository<Shop, Integer> {

}

Definitely it is the most simplest code snippet in the tutorial. But it requires the most high attention. The JpaRepository interface contains the basic operations which can be performed with any entity (CRUD operations). More information you can find on the official documentation page.

Here is a code of the ShopService interface:

public interface ShopService {
	
	public Shop create(Shop shop);
	public Shop delete(int id) throws ShopNotFound;
	public List<Shop> findAll();
	public Shop update(Shop shop) throws ShopNotFound;
	public Shop findById(int id);

}

And the implementation of the service interface:

import java.util.List;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.spr.exception.ShopNotFound;
import com.spr.model.Shop;
import com.spr.repository.ShopRepository;

@Service
public class ShopServiceImpl implements ShopService {
	
	@Resource
	private ShopRepository shopRepository;

	@Override
	@Transactional
	public Shop create(Shop shop) {
		Shop createdShop = shop;
		return shopRepository.save(createdShop);
	}
	
	@Override
	@Transactional
	public Shop findById(int id) {
		return shopRepository.findOne(id);
	}

	@Override
	@Transactional(rollbackFor=ShopNotFound.class)
	public Shop delete(int id) throws ShopNotFound {
		Shop deletedShop = shopRepository.findOne(id);
		
		if (deletedShop == null)
			throw new ShopNotFound();
		
		shopRepository.delete(deletedShop);
		return deletedShop;
	}

	@Override
	@Transactional
	public List<Shop> findAll() {
		return shopRepository.findAll();
	}

	@Override
	@Transactional(rollbackFor=ShopNotFound.class)
	public Shop update(Shop shop) throws ShopNotFound {
		Shop updatedShop = shopRepository.findOne(shop.getId());
		
		if (updatedShop == null)
			throw new ShopNotFound();
		
		updatedShop.setName(shop.getName());
		updatedShop.setEmplNumber(shop.getEmplNumber());
		return updatedShop;
	}

}

In this way the ShopRepository is used.

Controller

Finally I can use ShopSrviceImpl class in the controller. All JSP pages will be omitted, so you can find them source code on the GitHub.

@Controller
@RequestMapping(value="/shop")
public class ShopController {
	
	@Autowired
	private ShopService shopService;

	@RequestMapping(value="/create", method=RequestMethod.GET)
	public ModelAndView newShopPage() {
		ModelAndView mav = new ModelAndView("shop-new", "shop", new Shop());
		return mav;
	}
	
	@RequestMapping(value="/create", method=RequestMethod.POST)
	public ModelAndView createNewShop(@ModelAttribute Shop shop, 
			final RedirectAttributes redirectAttributes) {
		
		ModelAndView mav = new ModelAndView();
		String message = "New shop "+shop.getName()+" was successfully created.";
		
		shopService.create(shop);
		mav.setViewName("redirect:/index.html");
				
		redirectAttributes.addFlashAttribute("message", message);	
		return mav;		
	}
	
	@RequestMapping(value="/list", method=RequestMethod.GET)
	public ModelAndView shopListPage() {
		ModelAndView mav = new ModelAndView("shop-list");
		List<Shop> shopList = shopService.findAll();
		mav.addObject("shopList", shopList);
		return mav;
	}
	
	@RequestMapping(value="/edit/{id}", method=RequestMethod.GET)
	public ModelAndView editShopPage(@PathVariable Integer id) {
		ModelAndView mav = new ModelAndView("shop-edit");
		Shop shop = shopService.findById(id);
		mav.addObject("shop", shop);
		return mav;
	}
	
	@RequestMapping(value="/edit/{id}", method=RequestMethod.POST)
	public ModelAndView editShop(@ModelAttribute Shop shop,
			@PathVariable Integer id,
			final RedirectAttributes redirectAttributes) throws ShopNotFound {
		
		ModelAndView mav = new ModelAndView("redirect:/index.html");
		String message = "Shop was successfully updated.";

		shopService.update(shop);
		
		redirectAttributes.addFlashAttribute("message", message);	
		return mav;
	}
	
	@RequestMapping(value="/delete/{id}", method=RequestMethod.GET)
	public ModelAndView deleteShop(@PathVariable Integer id,
			final RedirectAttributes redirectAttributes) throws ShopNotFound {
		
		ModelAndView mav = new ModelAndView("redirect:/index.html");		
		
		Shop shop = shopService.delete(id);
		String message = "The shop "+shop.getName()+" was successfully deleted.";
		
		redirectAttributes.addFlashAttribute("message", message);
		return mav;
	}
	
}

spring-data-jpa-application

Summary

The Spring Data is very powerful weapon, it helps you develop an application more faster and avoid hundreds of boilerplate strings of code. Usage of Spring Data is the most convenient way to create a DAO layer in an application, so don’t ignore it in your projects.

About The Author

Mathematician, programmer, wrestler, last action hero... Java / Scala architect, trainer, entrepreneur, author of this blog

  • Nemanja

    Great article, I recently started learning Spring, and your blog is really helping me.

    • Nemanja

      Just one question, in ShopServiceImpl, is the update method correctly implemented, you did created new Shop object, set name and number, but after that you just returned updatedShop object without interaction with database (shopRepository).

      • Fruzenshtein

        Yeah it works properly
        When the update method is called, you are inside a read-write transaction. When you are working with already persisted object, all changes made to it are flushed back to the database when a read-write transaction is committed.

  • nice technology from Spring 😀
    fyi, those 2 of 3 links in preparation section have incorrect url

    • Fruzenshtein

      Thanks
      Now links are fixed =)

  • I have a question
    since you didn’t write the implementation of ShopRepository interface
    how can we test it?

    • Fruzenshtein

      All Spring’s code is already tested by the developers. If you will add some extra functionality in the repository class you should test it as always, using mocks and so on

  • Pablowiski

    You helped me a lot dude! Thank you.

  • Karthik

    whether hibernate is really needed? can’t we build applns using spring jpa, mvc & mysql? as u said, hibernate uses jpa implementations…

    Sry, Im juz a beginner… and its a plain doubt… 😉
    Ty… ur posts are gr8.

  • Raúl Ascencio

    thanks, it’s an awesome complement to the quickstart guide 🙂

  • rajan sellapan

    hello sir, thank you for your tutorial, I download and convert eclipse web project, and export to eclipse. when I run No index/home page coming, I could not call any page.
    please show one full url for how to access index, shop-list, shop-edit everything.
    http://localhost:8080/spr-mvc-hib/pages/index.jsp, when I start run the tomcat server automatically the index/ home page should come,
    please sorry for ignorance knowlede in spring mvc, I could not access. please help

  • Vishal Prajapati

    It wil be even more helpful if you also put a link of source download.

    • PA

      Hey, Vishal – Did you got the link to download this project ?

      Regards,
      Neha

  • James Gardiner

    Really like this example, but I am having a massive issue..

    When I run this demo, tomcat keeps printing..


    [2015-02-13 03:59:15,034] Artifact spr-data:war: Deploy took 4,803 milliseconds
    15:59:15.373 [http-bio-8080-exec-1] WARN o.s.web.servlet.PageNotFound – Request method ‘HEAD’ not supported
    15:59:15.393 [http-bio-8080-exec-2] WARN o.s.web.servlet.PageNotFound – Request method ‘HEAD’ not supported
    15:59:15.898 [http-bio-8080-exec-3] WARN o.s.web.servlet.PageNotFound – Request method ‘HEAD’ not supported
    15:59:15.901 [http-bio-8080-exec-4] WARN o.s.web.servlet.PageNotFound – Request method ‘HEAD’ not supported
    15:59:16.406 [http-bio-8080-exec-5] WARN o.s.web.servlet.PageNotFound – Request method ‘HEAD’ not supported
    15:59:16.409 [http-bio-8080-exec-6] WARN o.s.web.servlet.PageNotFound – Request method ‘HEAD’ not supported
    15:59:16.914 [http-bio-8080-exec-7] WARN o.s.web.servlet.PageNotFound – Request method ‘HEAD’ not supported
    15:59:16.917 [http-bio-8080-exec-8] WARN o.s.web.servlet.PageNotFound – Request method ‘HEAD’ not supported
    15:59:17.421 [http-bio-8080-exec-9] WARN o.s.web.servlet.PageNotFound – Request method ‘HEAD’ not supported
    15:59:17.424 [http-bio-8080-exec-10] WARN o.s.web.servlet.PageNotFound – Request method ‘HEAD’ not supported
    15:59:17.928 [http-bio-8080-exec-10] WARN o.s.web.servlet.PageNotFound – Request method ‘HEAD’ not supported


    Continuously. I have been googling the hell out of it but cannot find a solution.
    And your example is not the only example to do this.
    This is of course not desirable at all..
    I have tried running the demo from in intellij and eclipse with the same result..

    I am only new to Spring, this will be my first project using it. I want a Spring, JPA, Mysql, REST implementation..
    Any help appreciated…..

    Thanks

  • Andrew Jonca

    I had building errors related to jsp pages. The errors were resolved when one more dependency was added to the pom:

    javax.servlet
    jsp-api
    2.0

  • Sandeep

    Hi

    I have one doubt about implementation of spring data, have
    basic knowledge about spring data.

    I understand JPA and Hibernate, how it work. Hibernate provide
    the implementation for JPA.

    My questions, Can we work alone with Spring data to persist
    data in mysql or we need some provider like hibernate or toplink etc for
    midsize application

    • Hello, Sandeep

      As I remember you can add dependency to spring-data-jpa in pom.xml or in a gradle build file and all required dependencies will be uploaded automatically. You can try to do this, if it will not work, just add hibernate

      • sathish kumar

        Your reply did not answer @Sandeep question. He just asked whether or not to use ay JPA Provider. If I did not use with my Spring Data JPA application will work?

  • David

    Hi.

    Works great and very useful. I had to eliminate ShopNotFound class. Could you please post this class?. Thanks for your work…

  • mbeddedsoft

    Hello Alex,
    In this example why is there not an implementation for the ShopRepository interface? Is it because Spring Data is taking care of it?

    What about if I have a case where I need to add Custom Query support for my Entity class which has several one to many and a many to many relationship. I was thinking of actually creating the interface

    interface ITrackedItemRepository{
    getByState(int id);
    getByStateName(String name);
    }

    then implementing a custom class that implements these methods. But I was not thinking of annotating the class as a @Service? I thought I would create a TrackedItemRepositoryImpl which would then be used by multiple @Service instances. Is this incorrect thinking on my part?

    thank you,
    mbeddedsoft

  • Pingback: Spring Data (JPA) – JUGLviv()

  • Orlando Vasquez

    Could you post me the link for downloading the code example?

[data-image-id='gourmet_bg']
[data-image-id='gourmet_bg']
[data-image-id='gourmet_bg']
[data-image-id='gourmet_bg']
[data-image-id='gourmet_bg']
[data-image-id='gourmet_bg']
[data-image-id='gourmet']
[data-image-id='gourmet']
[data-image-id='gourmet']
[data-image-id='gourmet']
[data-image-id='gourmet']
[data-image-id='gourmet']
[data-image-id='gourmet']
[data-image-id='gourmet']
[data-image-id='gourmet']
[data-image-id='gourmet']
Close