DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • Spring Boot - How To Use Native SQL Queries | Restful Web Services
  • Composite Requests in Salesforce Are a Great Idea
  • A Guide to Enhanced Debugging and Record-Keeping
  • Less Code With Spring Data Rest

Trending

  • The Network Attach Problem Nobody Warns You About
  • Jakarta EE 12: Entering the Data Age of Enterprise Java
  • Introduction to Retrieval Augmented Generation (RAG)
  • What Nobody Tells You About Multimodal Data Pipelines for AI Training
  1. DZone
  2. Data Engineering
  3. Databases
  4. Introduction To Spring Data JPA With Inheritance in A REST Application

Introduction To Spring Data JPA With Inheritance in A REST Application

Spring is a platform designed to simplify the life of Java developers. This tutorial will delve into one of Spring Data JPA's key features, inheritance.

By 
Otavio Santana user avatar
Otavio Santana
DZone Core CORE ·
Updated Jun. 22, 23 · Tutorial
Likes (7)
Comment
Save
Tweet
Share
29.0K Views

Join the DZone community and get the full member experience.

Join For Free

Spring is a platform that has revolutionized how Java developers build applications, providing a robust framework and a wide range of tools to simplify the development process. One of the standout features of Spring is Spring Data JPA, which offers seamless integration between Java Persistence API (JPA) and the Spring Framework, making it easier to work with databases in a Java application.

In this tutorial, we will delve into a critical aspect of Spring Data JPA: inheritance. Inheritance is vital in object-oriented programming, allowing us to create hierarchies of classes that share common attributes and behaviors. Managing legacy can sometimes pose challenges when persisting these objects in a database.

Spring Data JPA provides an elegant solution to this challenge by supporting various inheritance strategies. Whether using single-table inheritance, joined-table inheritance, or table-per-class inheritance, Spring Data JPA provides the tools and abstractions to map and persist your object hierarchy in a database seamlessly.

This article will focus specifically on incorporating inheritance in a RESTful application using Spring Data JPA. We will explore how to define and map entity classes that utilize inheritance and how to perform CRUD (Create, Read, Update, Delete) operations on these entities using the powerful features of Spring Data JPA.

In the second part, we will cover the basic annotations on Spring Core and the Spring Web, focusing on Rest Controller; however, we did not create an application with a database connection.

Fortunately, this part's goal is to make a connection easier and clean. We'll use Spring Data because it reduces a lot of code and uses the JPA annotations.

To explore the JPA annotations with a repository, we'll create simple rest to handle a person and their tickets through plane, train, and bus. The foremost goal here is to explore the heritage of both the JPA and JSON serialization.

It is essential to highlight that there is an impedance mismatch. Thus objects are not RDBMS, and if we don't think about it will apply to performance and a bad design. 

Java
 




x
55


 
1
 
          
2
import javax.persistence.CascadeType;
3
import javax.persistence.Column;
4
import javax.persistence.Entity;
5
import javax.persistence.FetchType;
6
import javax.persistence.GeneratedValue;
7
import javax.persistence.GenerationType;
8
import javax.persistence.Id;
9
import javax.persistence.OneToMany;
10
import javax.validation.constraints.NotBlank;
11
import java.util.Collections;
12
import java.util.List;
13
import java.util.Objects;
14
 
          
15
@Entity
16
public class Person  {
17
 
          
18
    @Id
19
    @GeneratedValue(strategy = GenerationType.AUTO)
20
    private Long id;
21
 
          
22
    @NotBlank(message = "the name is mandatory in person")
23
    private String name;
24
 
          
25
    @Column
26
    private String city;
27
 
          
28
    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
29
    private List<Ticket> tickets;
30
 
          
31
    public Long getId() {
32
        return id;
33
    }
34
 
          
35
    public String getName() {
36
        return name;
37
    }
38
 
          
39
    public String getCity() {
40
        return city;
41
    }
42
 
          
43
    public List<Ticket> getTickets() {
44
        if(Objects.isNull(tickets)) {
45
            return Collections.emptyList();
46
        }
47
        return tickets;
48
    }
49
 
          
50
    void update(Person person) {
51
        this.city = person.city;
52
        this.name = person.name;
53
    }
54
 //...   
55
}



Only to show the heritage, there is a Ticket as an abstract class with some specialization. We used the Ticket class as an entity with a single table strategy, and in Jackson, the values of the subtype both are using the field type.

Java
 




xxxxxxxxxx
1
86


 
1
@Entity
2
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
3
@DiscriminatorColumn(name = "type", discriminatorType = DiscriminatorType.STRING)
4
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
5
@JsonSubTypes({@JsonSubTypes.Type(value = BoatTicket.class, name = "BOAT"),
6
        @JsonSubTypes.Type(value = BusTicket.class, name = "BUS"),
7
        @JsonSubTypes.Type(value = PlaneTicket.class, name = "PLANE")
8
})
9
public abstract class Ticket {
10
 
          
11
    @Id
12
    @GeneratedValue(strategy = GenerationType.AUTO)
13
    private Long id;
14
 
          
15
    @Column
16
    private BigDecimal value;
17
 
          
18
    public BigDecimal getValue() {
19
        return value;
20
    }
21
 
          
22
    public abstract TicketType getType();
23
 
          
24
    @Override
25
    public boolean equals(Object o) {
26
        if (this == o) {
27
            return true;
28
        }
29
        if (o == null || getClass() != o.getClass()) {
30
            return false;
31
        }
32
        Ticket ticket = (Ticket) o;
33
        return Objects.equals(id, ticket.id);
34
    }
35
 
          
36
    @Override
37
    public int hashCode() {
38
        return Objects.hashCode(id);
39
    }
40
 
          
41
    @Override
42
    public String toString() {
43
        return "Ticket{" +
44
                "id=" + id +
45
                ", value=" + value +
46
                '}';
47
    }
48
}
49
 
          
50
import javax.persistence.DiscriminatorValue;
51
import javax.persistence.Entity;
52
 
          
53
@Entity
54
@DiscriminatorValue("PLANE")
55
public class PlaneTicket extends Ticket {
56
 
          
57
    @JsonIgnore
58
    @Override
59
    public TicketType getType() {
60
        return TicketType.PLAIN;
61
    }
62
}
63
 
          
64
 
          
65
@Entity
66
@DiscriminatorValue("BUS")
67
public class BusTicket extends Ticket {
68
 
          
69
    @JsonIgnore
70
    @Override
71
    public TicketType getType() {
72
        return TicketType.BUS;
73
    }
74
}
75
 
          
76
 
          
77
@Entity
78
@DiscriminatorValue("BOAT")
79
public class BoatTicket extends Ticket {
80
 
          
81
    @JsonIgnore
82
    @Override
83
    public TicketType getType() {
84
        return TicketType.BOAT;
85
    }
86
}



The repository class integrates the database smoothly because the developer does not need to handle the implementation but with an interface. This repository has several features, such as query by method, and uses the Query annotation to execute queries without handling the undertaking.

Java
 




xxxxxxxxxx
1


 
1
import org.springframework.data.jpa.repository.JpaRepository;
2
import org.springframework.stereotype.Repository;
3
 
          
4
@Repository
5
interface PersonRepository extends JpaRepository<Person, Long> {
6
}



The last layer is the controller, where we'll do a tight integration with the repository once it is a light application. The PersonController has pagination features beyond the CRUD operation.

Java
 




xxxxxxxxxx
1
58


 
1
 
          
2
import org.springframework.data.domain.Page;
3
import org.springframework.data.domain.PageRequest;
4
import org.springframework.data.domain.Sort;
5
import org.springframework.http.HttpStatus;
6
import org.springframework.web.bind.annotation.DeleteMapping;
7
import org.springframework.web.bind.annotation.GetMapping;
8
import org.springframework.web.bind.annotation.PathVariable;
9
import org.springframework.web.bind.annotation.PostMapping;
10
import org.springframework.web.bind.annotation.PutMapping;
11
import org.springframework.web.bind.annotation.RequestBody;
12
import org.springframework.web.bind.annotation.RequestMapping;
13
import org.springframework.web.bind.annotation.RequestParam;
14
import org.springframework.web.bind.annotation.RestController;
15
import org.springframework.web.server.ResponseStatusException;
16
 
          
17
import java.util.stream.Stream;
18
 
          
19
@RestController
20
@RequestMapping("users")
21
public class PersonController {
22
 
          
23
    private static final int SIZE = 10;
24
 
          
25
    private final PersonRepository repository;
26
 
          
27
    public PersonController(PersonRepository repository) {
28
        this.repository = repository;
29
    }
30
 
          
31
    @GetMapping
32
    public Stream<Person> findAll(@RequestParam(value = "page", defaultValue = "0") int page) {
33
        Page<Person> people = this.repository.findAll(PageRequest.of(page, SIZE, Sort.by("name", "id")));
34
        return people.get();
35
    }
36
 
          
37
    @GetMapping("{id}")
38
    public Person findById(@PathVariable Long id) {
39
        return this.repository.findById(id).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
40
    }
41
    @PostMapping
42
    public Person insert(@RequestBody Person person) {
43
        return this.repository.save(person);
44
    }
45
 
          
46
    @PutMapping("{id}")
47
    public Person update(@PathVariable Long id, @RequestBody Person person) {
48
        Person personDatabase = this.repository.findById(id)
49
                .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
50
        personDatabase.update(person);
51
        return this.repository.save(personDatabase);
52
    }
53
 
          
54
    @DeleteMapping("{id}")
55
    public void delete(@PathVariable Long id) {
56
            this.repository.deleteById(id);
57
    }
58
}



In this tutorial, we explored the Spring Data JPA API basics using the inheritance feature on both JPA and JSON. Spring has several resources that allow us to create a REST application with a database integration with a couple of classes. It is essential to say that it is a first step in the JPA and Spring world, where there are references to go deep below.

References

  • Building a RESTful Web Service
  • Serving Web Content with Spring MVC
  • Building REST services with Spring
  • Accessing Data with JPA
  • LeaseWeb API Design Standards
  • Hibernate Inheritance Mapping
  • Glory of REST
  • Source Code
REST Web Protocols Spring Data Spring Framework Inheritance (object-oriented programming) Database

Opinions expressed by DZone contributors are their own.

Related

  • Spring Boot - How To Use Native SQL Queries | Restful Web Services
  • Composite Requests in Salesforce Are a Great Idea
  • A Guide to Enhanced Debugging and Record-Keeping
  • Less Code With Spring Data Rest

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook