Spring Boot @Repository

Spring Boot @Repository tutorial shows how to use the @Repository annotation in a Spring application.

Spring is a popular Java application framework and Spring Boot is an evolution of Spring that helps create stand-alone, production-grade Spring based applications easily.

@Repository

@Repository is a Spring annotation that indicates that the decorated class is a repository. A repository is a mechanism for encapsulating storage, retrieval, and search behavior which emulates a collection of objects. It is a specialization of the @Component annotation allowing for implementation classes to be autodetected through classpath scanning.

@ComponentScan ensures that the classes decorated with @Component and their derivatives including @Repository are found and registered as Spring beans. @ComponentScan is automatically included with @SpringBootApplication.

Spring Boot @Repository example

The following application demonstrates the usage of @Repository. It shows a list of countries in an HTML table to the user.

$ tree
.
├── pom.xml
└── src
    ├── main
    │   ├── java
    │   │   └── com
    │   │       └── zetcode
    │   │           ├── Application.java
    │   │           ├── bean
    │   │           │   └── Country.java
    │   │           ├── controller
    │   │           │   └── MyController.java
    │   │           ├── repository
    │   │           │   └── CountryRepository.java
    │   │           └── service
    │   │               ├── CountryService.java
    │   │               └── ICountryService.java
    │   └── resources
    │       ├── application.yml
    │       ├── import.sql
    │       ├── static
    │       │   └── index.html
    │       └── templates
    │           └── showCountries.ftl
    └── test
        └── java

This is the project structure.

pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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>com.zetcode</groupId>
    <artifactId>SpringBootRepository</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.9.RELEASE</version>
</parent>  

<dependencies>
    
    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <scope>runtime</scope>
    </dependency>
    
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <optional>true</optional>
    </dependency>     
    
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-freemarker</artifactId>
    </dependency>  
    
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>    
    
</dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>            
        </plugins>
    </build>         
</project>

This is the Maven build file. The h2 dependency includes the H2 database driver.

Spring Boot starters are a set of convenient dependency descriptors which greatly simplify Maven configuration. The spring-boot-starter-parent has some common configurations for a Spring Boot application. The spring-boot-devtools includes some Spring Boot developer tools. The spring-boot-starter-web-freemarker is a starter for building web applications with Freemarker template engine. It uses Tomcat as the default embedded container. The spring-boot-starter-data-jpa is a starter for using Spring Data JPA with Hibernate.

The spring-boot-maven-plugin provides Spring Boot support in Maven, allowing us to package executable JAR or WAR archives. Its spring-boot:run goal runs the Spring Boot application.

application.yml
server:
    port: 8086
    context-path: /SpringBootRepository

spring: 
    main:
        banner-mode: "off"     
    jpa:
        database: h2
        hibernate:
            dialect: org.hibernate.dialect.H2Dialect
            ddl-auto: create-drop

logging: 
    level: 
        org: 
            springframework: ERROR

In the application.yml file we write various configuration settings of a Spring Boot application. The port sets for server port and the context-path context path (application name). After these settings, we access the application at localhost:8086/SpringBootRepository/. With the banner-mode property we turn off the Spring banner.

The JPA database value specifies the target database to operate on. We specify the Hibernate dialect, org.hibernate.dialect.H2Dialect in our case. The ddl-auto is the data definition language mode; the create-drop option automatically creates and drops the database schema.

The H2 database is run in memory. Also, we set the logging level for spring framework to ERROR. The application.yml file is located in the in the src/main/resources directory.

import.sql
INSERT INTO Countries(Name, Population) VALUES('China', 1382050000);
INSERT INTO Countries(Name, Population) VALUES('India', 1313210000);
INSERT INTO Countries(Name, Population) VALUES('USA', 324666000);
INSERT INTO Countries(Name, Population) VALUES('Indonesia', 260581000);
INSERT INTO Countries(Name, Population) VALUES('Brazil', 207221000);
INSERT INTO Countries(Name, Population) VALUES('Pakistan', 196626000);
INSERT INTO Countries(Name, Population) VALUES('Nigeria', 186988000);
INSERT INTO Countries(Name, Population) VALUES('Bangladesh', 162099000);
INSERT INTO Countries(Name, Population) VALUES('Nigeria', 186988000);
INSERT INTO Countries(Name, Population) VALUES('Russia', 146838000);
INSERT INTO Countries(Name, Population) VALUES('Japan', 126830000);
INSERT INTO Countries(Name, Population) VALUES('Mexico', 122273000);
INSERT INTO Countries(Name, Population) VALUES('Philippines', 103738000);
INSERT INTO Countries(Name, Population) VALUES('Ethiopia', 101853000);
INSERT INTO Countries(Name, Population) VALUES('Vietnam', 92700000);
INSERT INTO Countries(Name, Population) VALUES('Egypt', 92641000);
INSERT INTO Countries(Name, Population) VALUES('Germany', 82800000);
INSERT INTO Countries(Name, Population) VALUES('the Congo', 82243000);
INSERT INTO Countries(Name, Population) VALUES('Iran', 82800000);
INSERT INTO Countries(Name, Population) VALUES('Turkey', 79814000);
INSERT INTO Countries(Name, Population) VALUES('Thailand', 68147000);
INSERT INTO Countries(Name, Population) VALUES('France', 66984000);
INSERT INTO Countries(Name, Population) VALUES('United Kingdom', 60589000);
INSERT INTO Countries(Name, Population) VALUES('South Africa', 55908000);
INSERT INTO Countries(Name, Population) VALUES('Myanmar', 51446000);
INSERT INTO Countries(Name, Population) VALUES('South Korea', 68147000);
INSERT INTO Countries(Name, Population) VALUES('Colombia', 49129000);
INSERT INTO Countries(Name, Population) VALUES('Kenya', 47251000);
INSERT INTO Countries(Name, Population) VALUES('Spain', 46812000);
INSERT INTO Countries(Name, Population) VALUES('Argentina', 43850000);
INSERT INTO Countries(Name, Population) VALUES('Ukraine', 42603000);
INSERT INTO Countries(Name, Population) VALUES('Sudan', 41176000);
INSERT INTO Countries(Name, Population) VALUES('Algeria', 40400000);
INSERT INTO Countries(Name, Population) VALUES('Poland', 38439000);

The schema is automatically created by Hibernate; later, the import.sql file is executed to fill the table with data.

Country.java
package com.zetcode.bean;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "Countries")
public class Country {
    
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String name;
    private int population;

    public Country() {
    }

    public Country(Long id, String name, int population) {
        this.id = id;
        this.name = name;
        this.population = population;
    }

    public Long getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public int getPopulation() {
        return population;
    }

    public void setPopulation(int population) {
        this.population = population;
    }

    @Override
    public String toString() {
        return "Country{" + "id=" + id + ", name=" + name
                + ", population=" + population + '}';
    }
}

This is the Country entity. Each entity must have at least two annotations defined: @Entity and @Id. Previously, we have set the ddl-auto option to create-drop which means that Hibernate will create the table schema from this entity.

@Entity
@Table(name = "Countries")
public class Country {

The @Entity annotation specifies that the class is an entity and is mapped to a database table. The @Table annotation specifies the name of the database table to be used for mapping.

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

The @Id annotation specifies the primary key of an entity and the @GeneratedValue gives the generation strategy for the values of primary keys.

CountryRepository.java
package com.zetcode.repository;

import com.zetcode.bean.Country;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface CountryRepository extends CrudRepository {

}

CountryRepository is decorated with the @Repository annotation.

By extending from the Spring CrudRepository, we have some methods for our data repository implemented, including findAll(). This saves some boilerplate code.

ICountryService.java
package com.zetcode.service;

import com.zetcode.bean.Country;
import java.util.List;

public interface ICountryService {

    public List<Country> findAll();
}

ICountryService contains the findAll() contract method.

CountryService.java
package com.zetcode.service;

import com.zetcode.bean.Country;
import com.zetcode.repository.CountryRepository;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class CountryService implements ICountryService {

    @Autowired
    private CountryRepository repository;

    @Override
    public List<Country> findAll() {

        List<Country> countries = (List<Country>) repository.findAll();
        return countries;
    }
}

CountryService contains the implementation of the findAll() method.

@Autowired
private CountryRepository repository;

CountryRepository is injected with the @Autowired annotation.

@Override
public List<Country> findAll() {

    List<Country> countries = (List<Country>) repository.findAll();
    return countries;

The findAll() method returns the list of all countries from the database.

MyController.java
package com.zetcode.controller;

import com.zetcode.bean.Country;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import com.zetcode.service.ICountryService;

@Controller
public class MyController {

    @Autowired
    ICountryService countryService;

    @RequestMapping("/showCountries")
    public ModelAndView findCities() {

        List<Country> countries = (List<Country>) countryService.findAll();

        Map<String, Object> params = new HashMap<>();
        params.put("countries", countries);

        return new ModelAndView("showCountries", params);
    }
}

MyController handles a request from the client.

@Controller
public class MyController {

A controller is annotated with @Controller annotation.

@Autowired
ICountryService countryService;

ICountryService is injected into the countryService field.

List<Country> countries = (List<Country>) countryService.findAll();

From the service object, we retrieve all countries with the findAll() method.

Map<String, Object> params = new HashMap<>();
params.put("countries", countries);

return new ModelAndView("showCountries", params);

The processing is send to the showCountries.ftl template file, along with the list of countries. We have provided the Freemarker dependency in the Maven POM file; therefore, Spring Boot figures out the extension for the view.

index.html
<!DOCTYPE html>
<html>
    <head>
        <title>Home page</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
    </head>
    <body>
        <p>
            <a href="showCountries">Show countries</a>
        </p>
    </body>
</html>

This is the home page. It contains a link to get all countries.

showCountries.ftl
<!DOCTYPE html>
<html>
    <head>
        <title>Show countries</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        </head>
    
    <body>

        <h2>List of countries</h2>
        
        <table>
            <tr>
                <th>Id</th>  
                <th>Name</th>  
                <th>Population</th>
            </tr>        

            <#list countries as country>
                <tr>
                    <td>${country.id}</td> 
                    <td>${country.name}</td> 
                    <td>${country.population}</td>
                </tr>
            </#list>        
        </table>     
    </body>
</html> 

This is the showCountries.ftl template file. With the #list directive, we show all the items from the list.

Application.java
package com.zetcode;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application  {
    
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

Application is the entry point which sets up Spring Boot application. The @SpringBootApplication annotation enables auto-configuration and component scanning. It is a convenience annotation for @Configuration, @EnableAutoConfiguration, and @ComponentScan annotations.

$ mvn -q spring-boot:run 

We run the application.

In this tutorial, we have shown how to use @Repository annotation in a Spring application. You might also be interested in the related tutorials: Spring Boot @PostConstruct tutorial, Spring Boot @Controller tutorial, Spring Boot @ExceptionHandler tutorial, Spring Boot upload file, Spring Boot @PathVariable tutorial, Spring Boot @RequestParam tutorial, Spring Boot @ResponseBody tutorial, Java tutorial.