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
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Last call! Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • The Magic of Spring Data
  • 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

Trending

  • A Simple, Convenience Package for the Azure Cosmos DB Go SDK
  • Teradata Performance and Skew Prevention Tips
  • Microsoft Azure Synapse Analytics: Scaling Hurdles and Limitations
  • Understanding Java Signals
  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
27.6K 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

  • The Magic of Spring Data
  • 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

Partner Resources

×

Comments
Oops! Something Went Wrong

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

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

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 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!