Thursday 1 August 2013

Spring MVC Hibernate Maven Example

In this article I want to examine an example of Spring MVC + Hibernate + Maven usage. This set of technology implies basic knowledge of the domain area. So I will try to explain all essential moments in detail. The other things which are out of topic, will be provided with links to more detail sources.

The goal

Creation of the sample web application, based on Spring MVC, Hibernate, Maven. Interface will be HTML-based. The application will support all CRUD operations: create, read, update, delete. As usually I will use MySQL as a database. The application will be work with football clubs entities, so be ready that the tutorial will be in a sport direction.
Spring-MVC-Hibernate-project-structure

Preparations

I will need one table in the database, and here is a code for its creation:
  1. CREATE TABLE `teams` (  
  2.   `id` int(6) NOT NULL AUTO_INCREMENT,  
  3.   `namevarchar(40) NOT NULL,  
  4.   `rating` int(6) NOT NULL,  
  5.   PRIMARY KEY (`id`)  
  6. ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;  
This table will be represented in the application with the class:
  1. @Entity  
  2. @Table(name="teams")  
  3. public class Team {  
  4.       
  5.     @Id  
  6.     @GeneratedValue  
  7.     private Integer id;  
  8.       
  9.     private String name;  
  10.       
  11.     private Integer rating;  
  12.       
  13.     public Integer getId() {  
  14.         return id;  
  15.     }  
  16.     public void setId(Integer id) {  
  17.         this.id = id;  
  18.     }  
  19.     public String getName() {  
  20.         return name;  
  21.     }  
  22.     public void setName(String name) {  
  23.         this.name = name;  
  24.     }  
  25.     public Integer getRating() {  
  26.         return rating;  
  27.     }  
  28.     public void setRating(Integer rating) {  
  29.         this.rating = rating;  
  30.     }  
  31.   
  32. }  

pom.xml


<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mvchib</groupId>
<artifactId>spring</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<properties>
<hibernate.version>4.2.0.Final</hibernate.version>
<mysql.connector.version>5.1.21</mysql.connector.version>
<spring.version>3.2.2.RELEASE</spring.version>
</properties>
<dependencies>
<!-- DB related dependencies -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.connector.version}</version>
</dependency>
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.12.1.GA</version>
</dependency>
<!-- SPRING -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- CGLIB is required to process @Configuration classes -->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2.2</version>
</dependency>
<!-- Servlet API and JSTL -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- Test -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.7</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test-mvc</artifactId>
<version>1.0.0.M1</version>
<scope>test</scope>
</dependency>
</dependencies>
<repositories>
<repository>
<id>spring-maven-milestone</id>
<name>Spring Maven Milestone Repository</name>
<url>http://maven.springframework.org/milestone</url>
</repository>
</repositories>
<build>
<finalName>spr-mvc-hib</finalName>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
The first important stop is WebAppConfig.java file, so let’s consider:
  1. @Configuration  
  2. @ComponentScan("com.sprhib")  
  3. @EnableWebMvc  
  4. @EnableTransactionManagement  
  5. @PropertySource("classpath:application.properties")  
  6. public class WebAppConfig {  
  7.       
  8.     private static final String PROPERTY_NAME_DATABASE_DRIVER = "db.driver";  
  9.     private static final String PROPERTY_NAME_DATABASE_PASSWORD = "db.password";  
  10.     private static final String PROPERTY_NAME_DATABASE_URL = "db.url";  
  11.     private static final String PROPERTY_NAME_DATABASE_USERNAME = "db.username";  
  12.       
  13.     private static final String PROPERTY_NAME_HIBERNATE_DIALECT = "hibernate.dialect";  
  14.     private static final String PROPERTY_NAME_HIBERNATE_SHOW_SQL = "hibernate.show_sql";  
  15.     private static final String PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN = "entitymanager.packages.to.scan";  
  16.       
  17.     @Resource  
  18.     private Environment env;  
  19.       
  20.     @Bean  
  21.     public DataSource dataSource() {  
  22.         DriverManagerDataSource dataSource = new DriverManagerDataSource();  
  23.           
  24.         dataSource.setDriverClassName(env.getRequiredProperty(PROPERTY_NAME_DATABASE_DRIVER));  
  25.         dataSource.setUrl(env.getRequiredProperty(PROPERTY_NAME_DATABASE_URL));  
  26.         dataSource.setUsername(env.getRequiredProperty(PROPERTY_NAME_DATABASE_USERNAME));  
  27.         dataSource.setPassword(env.getRequiredProperty(PROPERTY_NAME_DATABASE_PASSWORD));  
  28.           
  29.         return dataSource;  
  30.     }  
  31.       
  32.     @Bean  
  33.     public LocalSessionFactoryBean sessionFactory() {  
  34.         LocalSessionFactoryBean sessionFactoryBean = new LocalSessionFactoryBean();  
  35.         sessionFactoryBean.setDataSource(dataSource());  
  36.         sessionFactoryBean.setPackagesToScan(env.getRequiredProperty(PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN));  
  37.         sessionFactoryBean.setHibernateProperties(hibProperties());  
  38.         return sessionFactoryBean;  
  39.     }  
  40.       
  41.     private Properties hibProperties() {  
  42.         Properties properties = new Properties();  
  43.         properties.put(PROPERTY_NAME_HIBERNATE_DIALECT, env.getRequiredProperty(PROPERTY_NAME_HIBERNATE_DIALECT));  
  44.         properties.put(PROPERTY_NAME_HIBERNATE_SHOW_SQL, env.getRequiredProperty(PROPERTY_NAME_HIBERNATE_SHOW_SQL));  
  45.         return properties;    
  46.     }  
  47.       
  48.     @Bean  
  49.     public HibernateTransactionManager transactionManager() {  
  50.         HibernateTransactionManager transactionManager = new HibernateTransactionManager();  
  51.         transactionManager.setSessionFactory(sessionFactory().getObject());  
  52.         return transactionManager;  
  53.     }  
  54.       
  55.     @Bean  
  56.     public UrlBasedViewResolver setupViewResolver() {  
  57.         UrlBasedViewResolver resolver = new UrlBasedViewResolver();  
  58.         resolver.setPrefix("/WEB-INF/pages/");  
  59.         resolver.setSuffix(".jsp");  
  60.         resolver.setViewClass(JstlView.class);  
  61.         return resolver;  
  62.     }  
  63.   
  64. }  

At the start of the file you can see @EnableTransactionManagement, it enables Spring’s annotation-driven transaction management capability. Annotation @PropertySource(“classpath:application.properties”) – plugs in property file which located in the resource folder.
Pay your attention on three beans: transactionManager, sessionFactory, dataSource. These beans provide transaction management. 
  1. #DB properties:  
  2. db.driver=com.mysql.jdbc.Driver  
  3. db.url=jdbc:mysql://localhost:3306/hibnatedb  
  4. db.username=hibuser  
  5. db.password=root  
  6.   
  7. #Hibernate Configuration:  
  8. hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect  
  9. hibernate.show_sql=true  
  10. entitymanager.packages.to.scan=com.sprhib.model  
Thats all what is related to project preparation. Further I’m going to show you DAO and service layers.

DAO & Service layers

Here are DAOs and Services interfaces and implementations:
  1. public interface TeamDAO {  
  2.       
  3.     public void addTeam(Team team);  
  4.     public void updateTeam(Team team);  
  5.     public Team getTeam(int id);  
  6.     public void deleteTeam(int id);  
  7.     public List<team> getTeams();  
  8.   
  9. }  
  10. </team>  
Implementation of the DAO interface:
  1. @Repository  
  2. public class TeamDAOImpl implements TeamDAO {  
  3.       
  4.     @Autowired  
  5.     private SessionFactory sessionFactory;  
  6.       
  7.     private Session getCurrentSession() {  
  8.         return sessionFactory.getCurrentSession();  
  9.     }  
  10.   
  11.     public void addTeam(Team team) {  
  12.         getCurrentSession().save(team);  
  13.     }  
  14.   
  15.     public void updateTeam(Team team) {  
  16.         Team teamToUpdate = getTeam(team.getId());  
  17.         teamToUpdate.setName(team.getName());  
  18.         teamToUpdate.setRating(team.getRating());  
  19.         getCurrentSession().update(teamToUpdate);  
  20.           
  21.     }  
  22.   
  23.     public Team getTeam(int id) {  
  24.         Team team = (Team) getCurrentSession().get(Team.class, id);  
  25.         return team;  
  26.     }  
  27.   
  28.     public void deleteTeam(int id) {  
  29.         Team team = getTeam(id);  
  30.         if (team != null)  
  31.             getCurrentSession().delete(team);  
  32.     }  
  33.   
  34.     @SuppressWarnings("unchecked")  
  35.     public List<team> getTeams() {  
  36.         return getCurrentSession().createQuery("from Team").list();  
  37.     }  
  38.   
  39. }  
  40. </team>  
Annotation @Repository Indicates that an annotated class is a “DAO”.
  1. public interface TeamService {  
  2.       
  3.     public void addTeam(Team team);  
  4.     public void updateTeam(Team team);  
  5.     public Team getTeam(int id);  
  6.     public void deleteTeam(int id);  
  7.     public List<team> getTeams();  
  8.   
  9. }  
  10. </team>  
Implementation of the Service interface:
  1. @Service  
  2. @Transactional  
  3. public class TeamServiceImpl implements TeamService {  
  4.       
  5.     @Autowired  
  6.     private TeamDAO teamDAO;  
  7.   
  8.     public void addTeam(Team team) {  
  9.         teamDAO.addTeam(team);        
  10.     }  
  11.   
  12.     public void updateTeam(Team team) {  
  13.         teamDAO.updateTeam(team);  
  14.     }  
  15.   
  16.     public Team getTeam(int id) {  
  17.         return teamDAO.getTeam(id);  
  18.     }  
  19.   
  20.     public void deleteTeam(int id) {  
  21.         teamDAO.deleteTeam(id);  
  22.     }  
  23.   
  24.     public List<team> getTeams() {  
  25.         return teamDAO.getTeams();  
  26.     }  
  27.   
  28. }  
  29. </team>  
Annotation @Service indicates that an annotated class is a “Service”. Annotation @Transactional describes transaction attributes on a method or class.

Controllers & JSPs

Since I’m going to cover all CRUD operations, this chapter will be a little bit long. I will start from the base controller, it resposible for the Home page:
  1. @Controller  
  2. public class LinkController {  
  3.       
  4.     @RequestMapping(value="/")  
  5.     public ModelAndView mainPage() {  
  6.         return new ModelAndView("home");  
  7.     }  
  8.       
  9.     @RequestMapping(value="/index")  
  10.     public ModelAndView indexPage() {  
  11.         return new ModelAndView("home");  
  12.     }  
  13.   
  14. }  
It is simple enough, and here its JSP file:
  1. ...  
  2. <h1>Home page</h1>  
  3. <p>  
  4. ${message}<br>  
  5. <a href="${pageContext.request.contextPath}/team/add.html">Add new team</a><br>  
  6. <a href="${pageContext.request.contextPath}/team/list.html">Team list</a><br>  
  7. </p>  
  8. ...  
And here is a monster-class, the main controller of the application:
  1. @Controller  
  2. public class TeamController {  
  3.       
  4.     @Autowired  
  5.     private TeamService teamService;  
  6.       
  7.     @RequestMapping(value="/team/add")  
  8.     public ModelAndView addTeamPage() {  
  9.         ModelAndView modelAndView = new ModelAndView("add-team-form");  
  10.         modelAndView.addObject("team"new Team());  
  11.         return modelAndView;  
  12.     }  
  13.       
  14.     @RequestMapping(value="/team/add/process")  
  15.     public ModelAndView addingTeam(@ModelAttribute Team team) {  
  16.           
  17.         ModelAndView modelAndView = new ModelAndView("home");  
  18.         teamService.addTeam(team);  
  19.           
  20.         String message = "Team was successfully added.";  
  21.         modelAndView.addObject("message", message);  
  22.           
  23.         return modelAndView;  
  24.     }  
  25.       
  26.     @RequestMapping(value="/team/list")  
  27.     public ModelAndView listOfTeams() {  
  28.         ModelAndView modelAndView = new ModelAndView("list-of-teams");  
  29.           
  30.         List<team> teams = teamService.getTeams();  
  31.         modelAndView.addObject("teams", teams);  
  32.           
  33.         return modelAndView;  
  34.     }  
  35.       
  36.     @RequestMapping(value="/team/edit/{id}", method=RequestMethod.GET)  
  37.     public ModelAndView editTeamPage(@PathVariable Integer id) {  
  38.         ModelAndView modelAndView = new ModelAndView("edit-team-form");  
  39.         Team team = teamService.getTeam(id);  
  40.         modelAndView.addObject("team",team);  
  41.         return modelAndView;  
  42.     }  
  43.       
  44.     @RequestMapping(value="/team/edit/{id}", method=RequestMethod.POST)  
  45.     public ModelAndView edditingTeam(@ModelAttribute Team team, @PathVariable Integer id) {  
  46.           
  47.         ModelAndView modelAndView = new ModelAndView("home");  
  48.           
  49.         teamService.updateTeam(team);  
  50.           
  51.         String message = "Team was successfully edited.";  
  52.         modelAndView.addObject("message", message);  
  53.           
  54.         return modelAndView;  
  55.     }  
  56.       
  57.     @RequestMapping(value="/team/delete/{id}", method=RequestMethod.GET)  
  58.     public ModelAndView deleteTeam(@PathVariable Integer id) {  
  59.         ModelAndView modelAndView = new ModelAndView("home");  
  60.         teamService.deleteTeam(id);  
  61.         String message = "Team was successfully deleted.";  
  62.         modelAndView.addObject("message", message);  
  63.         return modelAndView;  
  64.     }  
  65.   
  66. }  
  67. </team>  
Almost all methods and request mappings are clear. But I want to underline that @RequestMapping for the editTeamPage() and edditingTeam() methods, contains different valuse for the method attribute.
And now it’s time to see JSPs for these mappings:
“Add new team” page:
  1. ...  
  2. <h1>Add team page</h1>  
  3. <p>Here you can add a new team.</p>  
  4. <form:form method="POST" commandname="team" action="${pageContext.request.contextPath}/team/add/process.html">  
  5. <table>  
  6. <tbody>  
  7.     <tr>  
  8.         <td>Name:</td>  
  9.         <td><form:input path="name"></form:input></td>  
  10.     </tr>  
  11.     <tr>  
  12.         <td>Rating:</td>  
  13.         <td><form:input path="rating"></form:input></td>  
  14.     </tr>  
  15.     <tr>  
  16.         <td><input type="submit" value="Add"></td>  
  17.         <td></td>  
  18.     </tr>  
  19. </tbody>  
  20. </table>  
  21. </form:form>  
  22.   
  23. <p><a href="${pageContext.request.contextPath}/index.html">Home page</a></p>  
  24. ...  
“List of teams” page:
  1. ...  
  2. <h1>List of teams</h1>  
  3. <p>Here you can see the list of the teams, edit them, remove or update.</p>  
  4. <c:foreach var="team" items="${teams}">  
  5. </c:foreach><table border="1px" cellpadding="0" cellspacing="0">  
  6. <thead>  
  7. <tr>  
  8. <th width="10%">id</th><th width="15%">name</th><th width="10%">rating</th><th width="10%">actions</th>  
  9. </tr>  
  10. </thead>  
  11. <tbody>  
  12. <tr>  
  13.     <td>${team.id}</td>  
  14.     <td>${team.name}</td>  
  15.     <td>${team.rating}</td>  
  16.     <td>  
  17.     <a href="${pageContext.request.contextPath}/team/edit/${team.id}.html">Edit</a><br>  
  18.     <a href="${pageContext.request.contextPath}/team/delete/${team.id}.html">Delete</a><br>  
  19.     </td>  
  20. </tr>  
  21.   
  22. </tbody>  
  23. </table>  
  24.   
  25. <p><a href="${pageContext.request.contextPath}/index.html">Home page</a></p>  
  26. ...  
“Edit team” page:
  1. ...  
  2. <h1>Edit team page</h1>  
  3. <p>Here you can edit the existing team.</p>  
  4. <p>${message}</p>  
  5. <form:form method="POST" commandname="team" action="${pageContext.request.contextPath}/team/edit/${team.id}.html">  
  6. <table>  
  7. <tbody>  
  8.     <tr>  
  9.         <td>Name:</td>  
  10.         <td><form:input path="name"></form:input></td>  
  11.     </tr>  
  12.     <tr>  
  13.         <td>Rating:</td>  
  14.         <td><form:input path="rating"></form:input></td>  
  15.     </tr>  
  16.     <tr>  
  17.         <td><input type="submit" value="Edit"></td>  
  18.         <td></td>  
  19.     </tr>  
  20. </tbody>  
  21. </table>  
  22. </form:form>  
  23.   
  24. <p><a href="${pageContext.request.contextPath}/index.html">Home page</a></p>  
  25. ...  
And a screenshot of the “List of teams” page:
Spring-MVC-Hibernate-CRUD-example

No comments:

Post a Comment