Enterprise Java

Spring JPA Data + Hibernate + MySQL + Maven

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 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 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 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.
 

Reference: Spring JPA Data + Hibernate + MySQL + Maven from our JCG partner Alexey Zvolinskiy at the Fruzenshtein’s notes blog.

Alexey Zvolinskiy

Alexey is a test developer with solid experience in automation of web-applications using Java, TestNG and Selenium. He is so much into QA that even after work he provides training courses for junior QA engineers.
Subscribe
Notify of
guest

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

17 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Guest
Guest
11 years ago

Hi Alexey

There is a typo in ShopService on lines 4 and 6 while throwing exceptions. Can you have a look on the code?

Halil Karakose
11 years ago

Hi Alexey
You should add inside ShopRepository. Otherwise ShopServiceImpl gives incompatible class errors.

This editor scrambles my comments but i think you got what i meant.

Alex
Alex
11 years ago
Reply to  Halil Karakose

Thanks for the comment
I didn’t publish this article here, but you can see the original version on my blog, and there everything is ok:

http://fruzenshtein.com/spring-jpa-data-hibernate-mysql/

Byron Kiourtzoglou
11 years ago
Reply to  Halil Karakose

We have corrected the mistake here also. Sorry for the inconvenience.

Artit Udomsomruedee
Artit Udomsomruedee
11 years ago

Cool Dude!!!

Caleb
Caleb
11 years ago

This tutorial says maven but doesn’t give the specifics of what the pom file would need to look like for this project.

Fruzenshtein
11 years ago
Reply to  Caleb

I put link to the GitHub specialy for those who want to see details of the project. So you need to be more attentive

zax
zax
11 years ago
Reply to  Fruzenshtein

what is the github link for this project. thanks

saravanan
saravanan
10 years ago
Reply to  zax
ola
ola
11 years ago

Hello, thanks for this example!

I am begginer in Spring and I want to see details of the project (maven + your marker about “Initializer class will be omitted” ) – but I can’t find your “I put link to the GitHub” ….

Leo
Leo
11 years ago
Reply to  ola

Read line under Controller.

Joe
Joe
11 years ago

The application.property file is missing
#MessageSource
message.source.basename=i18n/messages
message.source.use.code.as.default.message=true

on github

shafat
shafat
10 years ago

In the above example,

If we would like to add spring-security code.
What steps would be required.?

tovna
tovna
9 years ago

I’m following this tutorial but I’m getting this error:

Error creating bean with name ‘ShopRepository’: Invocation of init method failed; nested exception is java.lang.AbstractMethodError: org.springframework.data.jpa.repository.support.LockModeRepositoryPostProcessor.postProcess(Lorg/springframework/aop/framework/ProxyFactory;Lorg/springframework/data/repository/core/RepositoryInformation;)V

I’ve also tried @Repository annotation on ShopRepository but no success. Do you have a clue about this?

Walk
9 years ago
Reply to  tovna

I have a problem same with you, do you know how to fix it now?

Pawel
Pawel
9 years ago

Hi Alexey,

You have forgotten to add in pom file one dependency:

javax.servlet.jsp
jsp-api
2.2
provided

Otherwise, it does not compile project in Spring Tool Suite 3.6.4.RELEASE on Eclipse Luna. There are errors in jsp files.

David
David
8 years ago

Hi.

Why you use
@Resource
private ShopRepository shopRepository;

instead of
@Autowired
private ShopRepository shopRepository;

Thanks

Back to top button