Spring Data - JPA DataTable

. . 10 min read

display

This guide walks you through the process of building a Spring Boot application that uses JPA DataTable.

What You Will build

You will build a Spring Boot application with quick datatable fully configurable.

What You Need

  • A favorite text editor or IDE
  • JDK 1.8 or later
  • Gradle 4+ or Maven 3.2+

Setup Project With Spring Initializr

  • Navigate to Spring initializr.

  • Define the project name example: spring-boot-jpa-datatable

  • Choose Project Maven and the language Java.

  • Choose Your Java version ex: 17

  • Click add dependencies and select:

    • Spring Web
    • Thymeleaf
    • Lombok
    • Spring Data JPA
    • H2 Database
  • Click Generate.

Unzip the Downloaded Zip and open the Project using your favorite text editor or IDE

DataTable Dependency

Add the following Maven snippet to the pom.xml

<dependency>
    <groupId>com.github.darrachequesne</groupId>
    <artifactId>spring-data-jpa-datatables</artifactId>
    <version>5.1.0</version>
</dependency>

Create the Backend Resource

Define the User Entity

@Entity(name = "users")
@Getter
@Setter
public class User {

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private long userId;

  private String firstName;

  private String lastName;

  private String username;

  private String email;

  private boolean status;

}

Define the User Repository

@Repository
public interface UserRepository extends DataTablesRepository<User, Long> {}

Define the User Service

@Service
@RequiredArgsConstructor
public class UserService {

    private final Logger log = LoggerFactory.getLogger(UserService.class);

    private final UserRepository userRepository;

    public DataTablesOutput<User> findAllDatatable(DataTablesInput input) {
        log.debug("Request to get all Users");
        return userRepository.findAll(input);
    }

}

Define the User Rest API

@RestController
@RequestMapping("/api")
@RequiredArgsConstructor
public class UserResource {

  private final Logger log = LoggerFactory.getLogger(UserResource.class);
  private final UserService userService;

  /**
   * {@code GET  /users} : get all the users.
   *
   * @return the {@link DataTablesOutput} with status {@code 200 (OK)} and the list of users in body.
   */
  @GetMapping("/users")
  public DataTablesOutput<User> findAllDatatable(@Valid DataTablesInput input) {
    log.debug("REST request to get a page of Users");
    return userService.findAllDatatable(input);
  }

}

Define the User View

@Controller
public class UserView {

    @GetMapping("/")
    public String index() {
        return "index";
    }
}

Set The RepositoryFactoryBean to DataTablesRepositoryFactory and the base package to scan your repositories

@Configuration
@EnableJpaRepositories(repositoryFactoryBeanClass = DataTablesRepositoryFactoryBean.class, basePackages = "com.example.demo")
public class DataTablesConfiguration {}

Create data.sql under the resources folder to populate our table

INSERT INTO USERS (USER_ID, FIRST_NAME, LAST_NAME, EMAIL, USERNAME, STATUS)
VALUES (1, 'Andre', 'Denesik', '[email protected]', 'bruen.fletcher', true),
       (2, 'Shanel', 'Fahey', '[email protected]', 'kgleichner', true),
       (3, 'Rosanna', 'Kilback', '[email protected]', 'jamarcus20', false),
       (4, 'Americo', 'Franecki', '[email protected]', 'donnelly.napoleon', true),
       (5, 'Ova', 'Gusikowski', '[email protected]', 'dschneider', true),
       (6, 'Rhiannon', 'Schmitt', '[email protected]', 'crystel.kilback', true),
       (7, 'Eriberto', 'Frami', '[email protected]', 'corwin.jeffrey', false),
       (8, 'Ebba', 'Krajcik', '[email protected]', 'mozelle.bernier', true),
       (9, 'Beth', 'Balistreri', '[email protected]', 'olson.meagan', true),
       (10, 'Jesse', 'Wehner', '[email protected]', 'jada12', false),
       (11, 'Samanta', 'Kautzer', '[email protected]', 'katelin.strosin', true),
       (12, 'Lauretta', 'Deckow', '[email protected]', 'skylar.macejkovic', true),
       (13, 'Vella', 'Dibbert', '[email protected]', 'pcrona', true),
       (14, 'Kay', 'Haley', '[email protected]', 'shields.malika', true),
       (15, 'Brandon', 'Russel', '[email protected]', 'donnelly.dane', true),
       (16, 'Juvenal', 'Wolf', '[email protected]', 'yazmin.strosin', false),
       (17, 'Tad', 'Kuhic', '[email protected]', 'jstracke', true),
       (18, 'Pink', 'Block', '[email protected]', 'sanford.lysanne', true),
       (19, 'Kacie', 'Daugherty', '[email protected]', 'ghaag', true),
       (20, 'Helmer', 'Ziemann', '[email protected]', 'kbechtelar', false);

When runing the application, by default the data.sql will be executed before the entity will be created into the database, to prevent that add the following property under the application.properties

spring.jpa.defer-datasource-initialization=true

Create the Frontend View

Create the the index.html under the resources\templates folder

<!DOCTYPE HTML>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Spring Boot JPA Datatable</title>
    <!-- Bootstrap 5 css -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css    ">
    <!-- Datatable Bootstrap 5 css -->
    <link rel="stylesheet" href="https://cdn.datatables.net/1.11.3/css/dataTables.bootstrap5.min.css">
</head>
<body style="background-color: #6db751">

<div class="container py-5">
    <div class="row justify-content-center">
        <div class="col-12">
            <h1 class="text-light fw-bold">Spring Boot JPA DataTable</h1>
            <hr width="100px" height="10px" size="10px" class="bg-light">
        </div>
        <div class="col-6-md">
            <div class="card border-0 shadow-lg mt-4">
                <div class="card-header d-flex align-items-center">
                    <h4>List User</h4>
                </div>
                <div class="card-body">
                    <table id="userTable" class="table table-striped display shadow-sm" style="width:100%">
                        <thead>
                        <tr>
                            <th>First Name</th>
                            <th>Last Name</th>
                            <th>Username</th>
                            <th>Email</th>
                            <th>Status</th>
                        </tr>
                        </thead>
                    </table>
                </div>
            </div>
        </div>
    </div>
</div>

<!-- Jquery js -->
<script type="text/javascript" src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<!-- Jquery Datatable js -->
<script type="text/javascript" src="https://cdn.datatables.net/1.11.3/js/jquery.dataTables.min.js"></script>
<!-- Datatable Bootstrap 5 js -->
<script type="text/javascript" src="https://cdn.datatables.net/1.11.3/js/dataTables.bootstrap5.min.js"></script>
<!-- Datatable Serverside Spring fixer js -->
<script type="text/javascript" th:src="@{/js/jquery.spring-friendly.js}"></script>
<!-- Script js - initialize datable -->
<script>
    $('#userTable').DataTable({
        "processing": true,
        "serverSide": true,
        "ajax": "/api/users",
        columns: [
            {
                data: 'firstName',
            },
            {
                data: 'lastName',
            },
            {
                data: 'username',
                render: (data) => `<span class="shadow-sm px-2 py-1 rounded-3 bg-dark text-light">@${data}</span>`
            },
            {
                data: 'email',
                render: (data) => `<a class="text-dark" href="mailto: ${data}"  target="_blank">${data}</a>`
            },
            {
                data: 'status',
                render: (data) => `<span class="badge bg-${data ? 'success' : 'warning'}">${data ? 'active' : 'inactive'}</span>`
            },
        ]
    });
</script>
</body>
</html>

Create the jquery.spring-friendly.js under the resources\static folder

// From https://github.com/jquery/jquery/blob/master/src/serialize.js
// Overrides data serialization to allow Spring MVC to correctly map input parameters : column[0][data] now becomes column[0].data
(function ($) {
    let r20 = /%20/g, rbracket = /\[\]$/, rCRLF = /\r?\n/g, rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
        rsubmittable = /^(?:input|select|textarea|keygen)/i;

    function customBuildParams(prefix, obj, traditional, add) {
        let name;

        if (jQuery.isArray(obj)) {
            // Serialize array item.
            jQuery.each(obj, function (i, v) {
                if (traditional || rbracket.test(prefix)) {
                    // Treat each array item as a scalar.
                    add(prefix, v);

                } else {
                    // Item is non-scalar (array or object), encode its numeric
                    // index.
                    customBuildParams(prefix + "["
                        + (typeof v === "object" ? i : "") + "]", v,
                        traditional, add);
                }
            });

        } else if (!traditional && jQuery.type(obj) === "object") {
            // Serialize object item.
            for (name in obj) {
                // This is where the magic happens
                customBuildParams(prefix + "." + name, obj[name], traditional,
                    add);
            }

        } else {
            // Serialize scalar item.
            add(prefix, obj);
        }
    }

    $.param = function (a, traditional) {
        let prefix, s = [], add = function (key, value) {
            // If value is a function, invoke it and return its value
            value = jQuery.isFunction(value) ? value() : (value == null ? ""
                : value);
            s[s.length] = encodeURIComponent(key) + "="
                + encodeURIComponent(value);
        };

        // Set traditional to true for jQuery <= 1.3.2 behavior.
        if (traditional === undefined) {
            traditional = jQuery.ajaxSettings
                && jQuery.ajaxSettings.traditional;
        }

        // If an array was passed in, assume that it is an array of form
        // elements.
        if (jQuery.isArray(a) || (a.jquery && !jQuery.isPlainObject(a))) {
            // Serialize the form elements
            jQuery.each(a, function () {
                add(this.name, this.value);
            });

        } else {
            // If traditional, encode the "old" way (the way 1.3.2 or older
            // did it), otherwise encode params recursively.
            for (prefix in a) {
                customBuildParams(prefix, a[prefix], traditional, add);
            }
        }

        // Return the resulting serialization
        return s.join("&").replace(r20, "+");
    };
})(jQuery);

Test

Run the Java application as a SpringBootApplication with your IDE or use the following command line

 ./mvnw spring-boot:run

Now, you can open the URL below on your browser, default port is 8080 you can set it under the application.properties

http://localhost:8080

Summary

Congratulations 🎉 ! You've created quick datatable using Spring Boot, JPA & DataTable

Github

The tutorial can be found here on GitHub 👋

Blog

Check new tutorials on nonestack 👋

3
854

Recent articles

Spring Authorization Server - OAuth JWT

spring authorize server

This guide walks you through the process of building a Spring Boot Authorization Server JWT that uses Spring Security Security and Spring Security OAuth Resource. Applying the new way to configure Spring Authorization Server JWT without the Custom Filter

Continue reading
9 min read
.
1115 views

Spring Web - Rest Client

spring boot

Spring Framework introduces RestClient a new Fluent API to make synchronous HTTP requests

Continue reading
4 min read
.
1072 views

Spring Security - Basic Authentication

spring security

This guide walks you through the process of building a Spring boot application that uses Spring Security and Spring Data JPA. Applying the new way to configure Spring Security without the WebSecurityConfigurerAdapter

Continue reading
6 min read
.
923 views

Spring Boot - Get Started

spring boot

Spring Boot is a popular framework that simplifies and accelerate the process of developing a java based application

Continue reading
5 min read
.
874 views