Angular 9 SpringBoot MariaDB CRUD Example

In this tutorial, we show you Angular 9 Http Client & Spring Boot Server example that uses Spring JPA to do CRUD with MariaDB and Angular 9 as a front-end technology to make request and receive response.

Related Posts:
Spring Boot + Angular 9 example | Spring Data JPA + REST + MySQL CRUD example
Spring Boot + Angular 9 example | Spring Data JPA + REST + PostgreSQL CRUD example
Spring Boot + Angular 9 example | Spring Data + REST + Cassandra CRUD example
How to use Spring JPA with PostgreSQL | Spring Boot

Related Pages:

I. Technologies

– Java 1.8
– Maven 3.3.9
– Spring Tool Suite – Version 3.9.4.RELEASE
– Spring Boot: 2.0.4.RELEASE
– Angular 9
– RxJS 6
– MariaDB

II. Overview

spring-boot-angular-6-httpclient-spring-rest-api-data-mariadb + angular-http-service-architecture

1. Spring Boot Server

spring-boot-angular-6-httpclient-spring-rest-api-data-mariadb + spring-server-architecture

2. Angular 9 Client

spring-boot-angular-6-httpclient-spring-rest-api-data-mariadb + angular-client-architecture

III. Practice

1. Project Structure

1.1 Spring Boot Server

spring-boot-angular-6-httpclient-spring-rest-api-data-mariadb + springboot-structure

Customer class corresponds to entity and table customer.
CustomerRepository is an interface extends CrudRepository, will be autowired in CustomerController for implementing repository methods and custom finder methods.
CustomerController is a REST Controller which has request mapping methods for RESTful requests such as: getAllCustomers, postCustomer, deleteCustomer, deleteAllCustomers, findByAge, updateCustomer.
– Configuration for Spring Datasource and Spring JPA properties in
Dependencies for Spring Boot and MariaDB in pom.xml

1.2 Angular 9 Client

spring-boot-angular-6-httpclient-spring-rest-api-data-mariadb + angular-client-structure

In this example, we focus on:
– 4 components: customers-list, customer-details, create-customer, search-customer.
– 3 modules: FormsModule, HttpClientModule, AppRoutingModule.
customer.ts: class Customer (id, firstName, lastName)
customer.service.ts: Service for Http Client methods

2. How to do

2.1 Spring Boot Server

2.1.1 Dependency

2.1.2 Customer – Data Model


package com.ozenero.springrest.mariadb.model;

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

@Table(name = "customer")
public class Customer {

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

	@Column(name = "name")
	private String name;

	@Column(name = "age")
	private int age;

	@Column(name = "active")
	private boolean active;

	public Customer() {

	public Customer(String name, int age) { = name;
		this.age = age; = false;

	public long getId() {
		return id;

	public void setName(String name) { = name;

	public String getName() {

	public void setAge(int age) {
		this.age = age;

	public int getAge() {
		return this.age;

	public boolean isActive() {
		return active;

	public void setActive(boolean active) { = active;

	public String toString() {
		return "Customer [id=" + id + ", name=" + name + ", age=" + age + ", active=" + active + "]";
2.1.3 JPA Repository


package com.ozenero.springrest.mariadb.repo;

import java.util.List;


import com.ozenero.springrest.mariadb.model.Customer;

public interface CustomerRepository extends CrudRepository {
	List findByAge(int age);
2.1.4 REST Controller


package com.ozenero.springrest.mariadb.controller;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
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.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.ozenero.springrest.mariadb.model.Customer;
import com.ozenero.springrest.mariadb.repo.CustomerRepository;

@CrossOrigin(origins = "http://localhost:4200")
public class CustomerController {

	CustomerRepository repository;

	public List getAllCustomers() {
		System.out.println("Get all Customers...");

		List customers = new ArrayList<>();

		return customers;

	@PostMapping(value = "/customers/create")
	public Customer postCustomer(@RequestBody Customer customer) {

		Customer _customer = Customer(customer.getName(), customer.getAge()));
		return _customer;

	public ResponseEntity deleteCustomer(@PathVariable("id") long id) {
		System.out.println("Delete Customer with ID = " + id + "...");


		return new ResponseEntity<>("Customer has been deleted!", HttpStatus.OK);

	public ResponseEntity deleteAllCustomers() {
		System.out.println("Delete All Customers...");


		return new ResponseEntity<>("All customers have been deleted!", HttpStatus.OK);

	@GetMapping(value = "customers/age/{age}")
	public List findByAge(@PathVariable int age) {

		List customers = repository.findByAge(age);
		return customers;

	public ResponseEntity updateCustomer(@PathVariable("id") long id, @RequestBody Customer customer) {
		System.out.println("Update Customer with ID = " + id + "...");

		Optional customerData = repository.findById(id);

		if (customerData.isPresent()) {
			Customer _customer = customerData.get();
			return new ResponseEntity<>(, HttpStatus.OK);
		} else {
			return new ResponseEntity<>(HttpStatus.NOT_FOUND);
2.1.5 Configuration for Spring Datasource & JPA properties


2.2 Angular 9 Client

2.2.0 Create Service & Components

Run commands below:
ng g s Customer
ng g c CreateCustomer
ng g c CustomerDetails
ng g c CustomersList
ng g c SearchCustomers
On each Component selector, delete app- prefix, then change tslint.json rules"component-selector" to false.

2.2.1 Model


export class Customer {
    id: number;
    name: string;
    age: number;
    active: boolean;
2.2.2 CustomerService


import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';

  providedIn: 'root'
export class CustomerService {

  private baseUrl = 'http://localhost:8080/api/customers';

  constructor(private http: HttpClient) { }

  getCustomer(id: number): Observable<Object> {
    return this.http.get(`${this.baseUrl}/${id}`);

  createCustomer(customer: Object): Observable<Object> {
    return`${this.baseUrl}` + `/create`, customer);

  updateCustomer(id: number, value: any): Observable<Object> {
    return this.http.put(`${this.baseUrl}/${id}`, value);

  deleteCustomer(id: number): Observable<any> {
    return this.http.delete(`${this.baseUrl}/${id}`, { responseType: 'text' });

  getCustomersList(): Observable<any> {
    return this.http.get(`${this.baseUrl}`);

  getCustomersByAge(age: number): Observable<any> {
    return this.http.get(`${this.baseUrl}/age/${age}`);

  deleteAll(): Observable<any> {
    return this.http.delete(`${this.baseUrl}` + `/delete`, { responseType: 'text' });
2.2.3 Components

– CustomerDetailsComponent:

import { Component, OnInit, Input } from '@angular/core';
import { CustomerService } from '../customer.service';
import { Customer } from '../customer';

import { CustomersListComponent } from '../customers-list/customers-list.component';

  selector: 'customer-details',
  templateUrl: './customer-details.component.html',
  styleUrls: ['./customer-details.component.css']
export class CustomerDetailsComponent implements OnInit {

  @Input() customer: Customer;

  constructor(private customerService: CustomerService, private listComponent: CustomersListComponent) { }

  ngOnInit() {

  updateActive(isActive: boolean) {
      { name:, age: this.customer.age, active: isActive })
        data => {
          this.customer = data as Customer;
        error => console.log(error));

  deleteCustomer() {
        data => {
        error => console.log(error));


<div *ngIf="customer">
    <label>Name: </label> {{}}
    <label>Age: </label> {{customer.age}}
    <label>Active: </label> {{}}

  <span class="button is-small btn-primary" *ngIf='' (click)='updateActive(false)'>Inactive</span>

  <span class="button is-small btn-primary" *ngIf='!' (click)='updateActive(true)'>Active</span>

  <span class="button is-small btn-danger" (click)='deleteCustomer()'>Delete</span>


– CustomersListComponent:

import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs';

import { CustomerService } from '../customer.service';
import { Customer } from '../customer';

  selector: 'customers-list',
  templateUrl: './customers-list.component.html',
  styleUrls: ['./customers-list.component.css']
export class CustomersListComponent implements OnInit {

  customers: Observable;

  constructor(private customerService: CustomerService) { }

  ngOnInit() {

  deleteCustomers() {
        data => {
        error => console.log('ERROR: ' + error));

  reloadData() {
    this.customers = this.customerService.getCustomersList();



<div *ngFor="let customer of customers | async" style="width: 300px;">
  <customer-details [customer]='customer'></customer-details>

  <button type="button" class="button btn-danger" (click)='deleteCustomers()'>Delete All</button>

– CreateCustomerComponent:

import { Component, OnInit } from '@angular/core';

import { Customer } from '../customer';
import { CustomerService } from '../customer.service';

  selector: 'create-customer',
  templateUrl: './create-customer.component.html',
  styleUrls: ['./create-customer.component.css']
export class CreateCustomerComponent implements OnInit {

  customer: Customer = new Customer();
  submitted = false;

  constructor(private customerService: CustomerService) { }

  ngOnInit() {

  newCustomer(): void {
    this.submitted = false;
    this.customer = new Customer();

  save() {
      .subscribe(data => console.log(data), error => console.log(error));
    this.customer = new Customer();

  onSubmit() {
    this.submitted = true;;


<h3>Create Customer</h3>
<div [hidden]="submitted" style="width: 300px;">
  <form (ngSubmit)="onSubmit()">
    <div class="form-group">
      <label for="name">Name</label>
      <input type="text" class="form-control" id="name" required [(ngModel)]="" name="name">

    <div class="form-group">
      <label for="age">Age</label>
      <input type="text" class="form-control" id="age" required [(ngModel)]="customer.age" name="age">

    <button type="submit" class="btn btn-success">Submit</button>

<div [hidden]="!submitted">
  <h4>You submitted successfully!</h4>
  <button class="btn btn-success" (click)="newCustomer()">Add</button>

– SearchCustomersComponent:

import { Component, OnInit } from '@angular/core';
import { Customer } from '../customer';
import { CustomerService } from '../customer.service';

  selector: 'search-customers',
  templateUrl: './search-customers.component.html',
  styleUrls: ['./search-customers.component.css']
export class SearchCustomersComponent implements OnInit {

  age: number;
  customers: Customer[];

  constructor(private dataService: CustomerService) { }

  ngOnInit() {
    this.age = 0;

  private searchCustomers() {
      .subscribe(customers => this.customers = customers);

  onSubmit() {


<h3>Find By Age</h3>
<div style="width: 300px;">
  <form (ngSubmit)="onSubmit()">
    <div class="form-group">
      <label for="lastname">Age</label>
      <input type="text" class="form-control" id="age" required [(ngModel)]="age" name="age">

    <div class="btn-group">
      <button type="submit" class="btn btn-success">Submit</button>
  <li *ngFor="let customer of customers">
    <h4>{{}} - {{}} {{customer.age}}</h4>
2.2.4 AppRoutingModule


import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { CustomersListComponent } from './customers-list/customers-list.component';
import { CreateCustomerComponent } from './create-customer/create-customer.component';
import { SearchCustomersComponent } from './search-customers/search-customers.component';

const routes: Routes = [
    { path: '', redirectTo: 'customer', pathMatch: 'full' },
    { path: 'customer', component: CustomersListComponent },
    { path: 'add', component: CreateCustomerComponent },
    { path: 'findbyage', component: SearchCustomersComponent },

    imports: [RouterModule.forRoot(routes)],
    exports: [RouterModule]

export class AppRoutingModule { }

And AppComponent HTML for routing:

<div style="padding: 20px;">
  <h1 style="color: blue">{{title}}</h1>
    <a routerLink="customer" class="btn btn-primary active" role="button" routerLinkActive="active">Customers</a>
    <a routerLink="add" class="btn btn-primary active" role="button" routerLinkActive="active">Add</a>
    <a routerLink="findbyage" class="btn btn-primary active" role="button" routerLinkActive="active">Search</a>
2.2.5 AppModule


import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';

import { AppComponent } from './app.component';
import { CreateCustomerComponent } from './create-customer/create-customer.component';
import { CustomerDetailsComponent } from './customer-details/customer-details.component';
import { CustomersListComponent } from './customers-list/customers-list.component';
import { SearchCustomersComponent } from './search-customers/search-customers.component';
import { AppRoutingModule } from './app-routing.module';
import { HttpClientModule } from '@angular/common/http';

  declarations: [
  imports: [
  providers: [],
  bootstrap: [AppComponent]
export class AppModule { }

3. Run & Check Result

Build and Run Spring Boot project with commandlines: mvn clean install and mvn spring-boot:run.
– Run the Angular App with command: ng serve.

– Open browser for url http://localhost:4200/:
Add Customer:


Show Customers:

spring-boot-angular-6-httpclient-spring-rest-api-data-mariadb + show-customers

Click on Active button to update Customer status:

spring-boot-angular-6-httpclient-spring-rest-api-data-mariadb +update-customers

Search Customers by Age:

spring-boot-angular-6-httpclient-spring-rest-api-data-mariadb + search-customers

Delete a Customer:

spring-boot-angular-6-httpclient-spring-rest-api-data-mariadb + delete-customer

Delete All Customers:

spring-boot-angular-6-httpclient-spring-rest-api-data-mariadb + delete-all-customers

IV. Source Code


14 thoughts on “Angular 9 SpringBoot MariaDB CRUD Example”

  1. 306067 866219 There are some interesting points in time in this write-up but I dont know if I see all of them center to heart. There is some validity but I will take hold opinion until I look into it further. Very good article , thanks and we want far more! Added to FeedBurner as nicely 128599

  2. I had been wondering should anyone ever considered changing design of the blog? Its perfectly written. I enjoy what youve have got to say. But you could a bit more in the way of content so people could connect to it better. Youve got a lot of text for only having a couple of images. You may could space out better?

  3. I enjoy you because of all of your labor on this blog. My niece loves going through investigations and it is easy to understand why. We know all relating to the dynamic form you offer sensible things through the blog and in addition inspire participation from others on this concept plus our favorite child is actually becoming educated so much. Take pleasure in the rest of the new year. You’re the one performing a useful job.

  4. Hey, I simply hopped over in your web page by means of StumbleUpon. Not one thing I might in most cases learn, however I favored your feelings none the less. Thank you for making something price reading.

  5. 821863 634476Really fighter messages are supposed to amuse offer praise into the groom and bride. Initial time audio system watching more than the top places need to also remember you see, the senior guideline with the speaking, which is your particular person. finest man speeches brother 670846

  6. I want to convey my admiration for your generosity in support of people who really need assistance with this one matter. Your real commitment to passing the solution throughout had become rather effective and has without exception enabled those much like me to reach their dreams. Your amazing insightful recommendations implies a lot to me and extremely more to my fellow workers. Thanks a ton; from each one of us.

  7. It¡¦s really a great and helpful piece of information. I am satisfied that you simply shared this useful information with us. Please stay us up to date like this. Thank you for sharing.

  8. 137888 854595Spot up for this write-up, I truly believe this web web site requirements a terrific deal much more consideration. Ill likely to finish up again to read a good deal a lot more, a lot of thanks for that info. 776035

Leave a Reply

Your email address will not be published. Required fields are marked *