Showing posts with label Spring Web Services CRUD Tutorial with Hibernate and Maven. Show all posts
Showing posts with label Spring Web Services CRUD Tutorial with Hibernate and Maven. Show all posts

Spring Web Services CRUD Tutorial with Hibernate and Maven

Spring MVC CRUD Web Services with Hibernate (No XML) — 2026 Guide

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