Spring MVC CRUD Web Services with Hibernate (No XML)
In this tutorial, we will build a complete Spring MVC CRUD REST web
service backed by Hibernate and MySQL using
annotation-based configuration only — no web.xml, no
spring-servlet.xml.
You will learn how AbstractAnnotationConfigDispatcherServletInitializer
replaces web.xml, how to configure a DataSource,
SessionFactory, and HibernateTransactionManager as Spring
beans, and how to expose CRUD operations via a @RestController.
Project Structure
MyConfig.java (Java Config)
This is the central configuration class. It replaces the traditional
applicationContext.xml and spring-servlet.xml files.
package com.example.config;
import java.util.Properties;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import com.example.model.User;
@Configuration
@EnableWebMvc
@EnableTransactionManagement
@ComponentScan(basePackages = { "com.example" })
@PropertySource(value = { "classpath:application.properties" })
public class MyConfig {
@Autowired
private Environment environment;
@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(environment.getRequiredProperty("jdbc.class"));
dataSource.setUrl(environment.getRequiredProperty("jdbc.url"));
dataSource.setUsername(environment.getRequiredProperty("jdbc.user"));
dataSource.setPassword(environment.getRequiredProperty("jdbc.pass"));
System.out.println("Deep database " + dataSource);
return dataSource;
}
@Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
// sessionFactory.setPackagesToScan(new String[] {"com.example.model"});
sessionFactory.setAnnotatedClasses(User.class);
sessionFactory.setHibernateProperties(hibernateProperties());
System.out.println("deep session " + sessionFactory);
return sessionFactory;
}
private Properties hibernateProperties() {
Properties properties = new Properties();
//properties.put("hibernate.dialect", environment.getRequiredProperty("hibernate.dialect"));
properties.put("hibernate.show_sql", environment.getRequiredProperty("hibernate.show_sql"));
properties.put("hibernate.format_sql", environment.getRequiredProperty("hibernate.format_sql"));
properties.put("hibernate.hbm2ddl.auto",
environment.getRequiredProperty("hibernate.hbm2ddl.auto"));
System.out.println(properties);
return properties;
}
@Bean
public HibernateTransactionManager getTransactionManager() {
System.out.println("transaction "+"hello");
HibernateTransactionManager transactionManager = new HibernateTransactionManager();
transactionManager.setSessionFactory(sessionFactory().getObject());
System.out.println("transaction "+transactionManager);
return transactionManager;
}
@Bean
public CommonsMultipartResolver multipartResolver() {
CommonsMultipartResolver cm=new CommonsMultipartResolver();
cm.setMaxUploadSize(100000); return cm; }
}
FrontController.java (No web.xml)
This class replaces the traditional web.xml file. It extends
AbstractAnnotationConfigDispatcherServletInitializer and works in a standard
Servlet container (Tomcat, Jetty).
package com.example.controller;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
import com.example.config.MyConfig;
public class FrontController extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
// TODO Auto-generated method stub
return new Class[] {MyConfig.class};
}
@Override
protected Class<?>[] getServletConfigClasses() {
// TODO Auto-generated method stub
return null;
}
@Override
protected String[] getServletMappings() {
// TODO Auto-generated method stub
return new String[] {"/"};
}
}
UserController.java
The @RestController exposes five REST endpoints for CRUD operations. Spring
automatically converts Java objects to/from JSON via Jackson.
package com.example.controller;
import java.util.List;
import javax.websocket.server.PathParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.example.model.User;
import com.example.service.UserService;
@RestController
public class UserController {
@Autowired
private UserService userService;
@PostMapping(value= {"insert"})
public int addUser(@RequestBody User user) {
return userService.insert(user);
}
@PutMapping(value= {"update"})
public int updateUser(@RequestBody User user) {
return userService.update(user);
}
@DeleteMapping(value= {"delete/{id}"})
public int deleteUser(@PathVariable int id) {
return userService.delete(id);
}
@GetMapping(value= {"fetch/{id}"})
public User fetchUser(@PathVariable int id) {
return userService.fetch(id);
}
@GetMapping(value= {"fetchall"})
public List<User> fetchAllUser() {
return userService.fetchAll();
}
}
UserDao.java & UserDaoImpl.java
UserDao.java (Interface)
package com.example.dao;
import java.util.List;
import com.example.model.User;
public interface UserDao {
public int insert(User user);
public int delete(int id);
public int update(User user);
public User fetch(int id);
public List<User> fetchAll();
}
UserDaoImpl.java (Implementation)
package com.example.dao;
import java.util.List;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import org.hibernate.SessionFactory;
import org.hibernate.query.Query;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import com.example.model.User;
@Repository
public class UserDaoImpl implements UserDao {
@Autowired
private SessionFactory sessionFactory;
@Override
public int insert(User user) {
System.out.println(sessionFactory);
int id = (Integer) sessionFactory.getCurrentSession().save(user);
return id;
}
@Override
public int delete(int id) {
int i = 0;
User user = sessionFactory.getCurrentSession().get(User.class, id);
if (user != null) {
sessionFactory.getCurrentSession().delete(user);
i=1;
}
return i;
}
@Override
public int update(User user) {
int i=0;
User u = sessionFactory.getCurrentSession().get(User.class, user.getId());
u.setEmail(user.getEmail());
u.setName(user.getName());
if(u!=null) {
sessionFactory.getCurrentSession().update(u);
i=1;
}
return i;
}
@Override
public User fetch(int id) {
System.out.println(id);
User user = sessionFactory.getCurrentSession().get(User.class, id);
System.out.println(user);
if(user!=null) {
return user;
}
return new User();
}
@Override
public List<User> fetchAll() {
CriteriaBuilder cb = sessionFactory.getCurrentSession().getCriteriaBuilder();
CriteriaQuery<User> query = cb.createQuery(User.class);
Root<User> p = query.from(User.class);
query.select(p);
//query.where(cb.equal(p.get("statusStepOne"), 0));
//query.setFirstResult(0);
//query.setMaxResults(1);
Query<User> qq=sessionFactory.getCurrentSession().createQuery(query);
List<User> list = qq.getResultList();
return list;
}
}
User.java (Entity)
package com.example.model;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name="myrecords")
public class User {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private int id;
private String name;
private String email;
public User() {
super();
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
UserService.java & UserServiceImpl.java
UserService.java (Interface)
package com.example.service;
import java.util.List;
import com.example.model.User;
public interface UserService {
public int insert(User user);
public int delete(int id);
public int update(User user);
public User fetch(int id);
public List<User> fetchAll();
}
UserServiceImpl.java
package com.example.service;
import java.util.List;
import javax.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.example.dao.UserDao;
import com.example.model.User;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
@Override
@Transactional
public int insert(User user) {
return userDao.insert(user);
}
@Override
@Transactional
public int delete(int id) {
return userDao.delete(id);
}
@Override
@Transactional
public int update(User user) {
return userDao.update(user);
}
@Override
@Transactional
public User fetch(int id) {
return userDao.fetch(id);
}
@Override
@Transactional
public List<User> fetchAll() {
return userDao.fetchAll();
}
}
application.properties
jdbc.url=jdbc:mysql://localhost:3306/test
jdbc.class=com.mysql.jdbc.Driver
jdbc.pass=root
jdbc.user=root
hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
hibernate.show_sql = true
hibernate.format_sql = true
hibernate.hbm2ddl.auto = update
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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>SpringCurdWebServices</groupId>
<artifactId>SpringCurdWebServices</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<release>10</release>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.1</version>
<configuration>
<warSourceDirectory>WebContent</warSourceDirectory>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>5.1.1.RELEASE</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.2.17.Final</version>
</dependency>
<!-- Hibernate Validator -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.4.1.Final</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.3</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.12.1.GA</version>
</dependency>
</dependencies>
</project>
Frequently Asked Questions
How do I configure Spring MVC without web.xml?
Extend AbstractAnnotationConfigDispatcherServletInitializer and override
three methods: getRootConfigClasses(),
getServletConfigClasses(), and getServletMappings(). Spring
automatically detects this class and registers the DispatcherServlet.
What is @EnableWebMvc in Spring?
@EnableWebMvc imports the Spring MVC configuration from
WebMvcConfigurationSupport. It enables support for
@Controller, @RequestMapping, HTTP message converters (like
Jackson JSON), and view resolvers.
What is the difference between @Repository, @Service, and @Controller?
They are all specializations of @Component. @Repository is for
the data access layer and translates SQL exceptions. @Service is for
business logic. @Controller is for handling web requests. Using the right
one makes the code more readable and enables layer-specific features.
Why is @Transactional needed on service methods?
Hibernate requires an active transaction to perform inserts, updates, and deletes.
@Transactional tells Spring to wrap the method in a transaction, so the
Session is opened and committed automatically.
Why use CriteriaBuilder instead of HQL for fetchAll()?
Both work, but CriteriaBuilder provides type-safe queries that are checked at compile time. HQL is string-based and errors only appear at runtime. For simple queries, HQL is shorter; for complex dynamic queries, Criteria API is safer.
Conclusion
In this tutorial, you built a complete Spring MVC CRUD REST web
service using annotation-based configuration — no web.xml, no XML
config files. You learned how
AbstractAnnotationConfigDispatcherServletInitializer replaces the servlet
descriptor, how to configure Hibernate as Spring beans, and how to expose clean REST
endpoints with @RestController.
You can extend this project by adding validation with @Valid, error
handling with @ControllerAdvice, pagination with
CriteriaBuilder, or migrate to Spring Boot where all of
this configuration is auto-detected.
Related topics: Spring Boot REST API Tutorial, Spring Data JPA CRUD, Hibernate Criteria API, Spring Exception Handling, Spring Validation, Migrating Spring MVC to Spring Boot
No comments:
Post a Comment