Delving into Spring Data JPA: Mastering Mutual One-to-Many Dependencies

Ava Parker - Sep 10 - - Dev Community

In this article, we will explore the following subjects:

  • Interdependent bi-directional one-to-many relationships
  •  @Join column annotation: specifying the join column
  •  @JsonIgnore annotation: excluding properties from JSON serialization
  •  @Transient annotation: marking non-persistent fields

Let’s re-examine the same scenario involving User and Role entities.

User and role entities

As depicted, the User entity references the Role entity, and conversely, the Role entity references the User entity, thereby establishing a bi-directional interdependence. This facilitates navigation in both directions, from User to Role and vice versa.

Now, let’s analyze how Hibernate generates the table by default.Hibernate default table structure

Observe the foreign key reference to the ID of the t_role table in the t_user table. How does this translate to code? Please see below.

Defining the User Entity

Source: https://t8tech.com/it/data/exploring-spring-data-jpa-navigating-bidirectional-one-to-many-relationships/

package com.notyfyd.entity;
import javax.persistence.*;
@Entity@Table(name = "t_user")
public class User {
    @Id    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String firstName;
    private String lastName;
    private String mobile;
    @Column(unique = true)
    private String email;
    @ManyToOne    private Role role;

    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getFirstName() {
        return firstName;
    }
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
    public String getLastName() {
        return lastName;
    }
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
    public String getMobile() {
        return mobile;
    }
    public void setMobile(String mobile) {
        this.mobile = mobile;
    }
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }

    public Role getRole() {
        return role;
    }

    public void setRole(Role role) {
        this.role = role;
    }
}

I’m ready to assist you as a professional copywriter. Please provide the text you’d like me to rewrite, and I’ll create a unique version with a natural style in English, preserving the original formatting and meaning while adhering to beautiful literary English language and avoiding stylistic and grammatical errors.

@ManyToOneprivate Role role;

I'm at your service as a seasoned copywriter. Please provide the text you'd like me to rephrase, and I'll craft a distinctive version with a natural flow in English, maintaining the original structure and essence while upholding impeccable literary English language and avoiding stylistic and grammatical flaws.

The aforementioned transformation has triggered a seismic shift. Currently, definitions are being established on both sides of the relationship.

Entity Role

package com.notyfyd.entity;
import javax.persistence.*;
import java.util.List;

@Entity@Table(name = "t_role")
public class Role {
    @Id    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String title;
    private String summary;

    @OneToMany(targetEntity = User.class)
    private List users;
    public Long getId() {
        return this.id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getTitle() {
        return this.title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public String getSummary() {
        return this.summary;
    }
    public void setSummary(String summary) {
        this.summary = summary;
    }
    public List getUsers() {
        return users;
    }
    public void setUsers(List users) {
        this.users = users;
    }
}

Position Repository

package com.notyfyd.repository;

import com.notyfyd.entity.Role;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.Optional;

@Repositorypublic interface RoleRepository extends JpaRepository {
    Optional findByTitle(String title);
}

Client Profile Nexus

package com.notyfyd.repository;

import com.notyfyd.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.Optional;

@Repositorypublic interface UserRepository extends JpaRepository {
    Optional retrieveUserByEmail(String email);
}

Role Management Service

We’re building upon the same codebase established in our previous installment (Part 2)

package com.notyfyd.service;

import com.notyfyd.entity.Role;
import com.notyfyd.repository.RoleRepository;
import com.notyfyd.repository.UserRepository;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Servicepublic class RoleService {

    private RoleRepository roleRepository;

    private UserRepository userRepository;

    public RoleService(RoleRepository roleRepository, UserRepository userRepository) {
        this.roleRepository = roleRepository;
        this.userRepository = userRepository;
    }

    /
     * Establish a new role accompanied by users
     */

    @Transactional    public ResponseEntity createRole(Role role) {

        Role newRole = new Role();
        newRole.setName(role.getName());
        newRole.setDescription(role.getDescription());

        newRole.setUsers(role.getUsers());
        Role savedRole = roleRepository.save(newRole);
        if (roleRepository.findById(savedRole.getId()).isPresent()) {
            return ResponseEntity.accepted().body("Role and Users Successfully Established");
        } else
            return ResponseEntity.unprocessableEntity().body("Failed to Establish Specified Role");
    }

    /
     * Remove a specified role given the id
     */
    public ResponseEntity removeRole(Long id) {
        if (roleRepository.findById(id).isPresent()) {
            roleRepository.deleteById(id);
            if (roleRepository.findById(id).isPresent()) {
                return ResponseEntity.unprocessableEntity().body("Failed to Remove the Specified Record");
            } else return ResponseEntity.ok().body("Specified Record Successfully Removed");
        } else
            return ResponseEntity.unprocessableEntity().body("No Records Found");
    }
}

Privilege Administrator

package com.notyfyd.controller;

import com.notyfyd.entity.Role;
import com.notyfyd.service.RoleService;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;


@RestControllerpublic class RoleController {

    private RoleService roleService;

    public RoleController(RoleService roleService) {
        this.roleService = roleService;
    }

    @PostMapping("/role/create")    public ResponseEntity createRole(@RequestBody Role role) {
        return  roleService.addRole(role);
    }
    @DeleteMapping("/role/delete/{id}")    public ResponseEntity deleteRole(@PathVariable Long id) {
        return roleService.deleteRole(id);
    }
}

Configuration Parameters File

server.port=2003
spring.datasource.driver-class-name= org.postgresql.Driver
spring.datasource.url= jdbc:postgresql://192.168.64.6:30432/jpa-test
spring.datasource.username = postgres
spring.datasource.password = root
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=create

I’m ready to assist you as a professional copywriter. Please provide the text you’d like me to rewrite, and I’ll create a unique version with a natural style in English, preserving the original formatting and meaning while adhering to beautiful literary English language and avoiding stylistic and grammatical errors.

It’s time to launch the application.

Fire up Postman and dispatch a Post request to create two users, assigning them the ADMIN role. The requisite JSON Object is provided below.

. . . . . .
Terabox Video Player