Tuesday, February 22, 2022

OneToMany Relationship In Spring Boot With Hibernate And Jpa

springboot,java,hibernate,jpa,onetomany,programming,software development,technology
We will learn how to implement unidirectional relationships in One-To-Many associations in this tutorial.

1. What is a One-To-Many association

Consider the following example: John is the owner of a popular blogging site with a large number of Blogs on a variety of topics. So, in this case, One Owner is the author of Many Blogs. As an example, one publishing house may have published books by many authors, or one blog may have many reviews. One entity has a relationship with a list/set of entities in a One-To-Many relationship.

Consider the following example of the Owner's association with the Blogs:
// Blog class
public class Blog {
	private Int id;
	…
	private String title;
	…
}

// Owner class
public class Owner {
	private Int id;
	…
	private List<Blog> blogs; 
	…
}
The key point is to pay attention to the declaration of the blogs variable in the Owner class. Because Owner has several blogs, the Owner class should contain a List of blogs. As a result, Many (List) Blog is associated with One Owner - this is a One-To-Many relationship.

JAVA,Software Development,Hibernate,Technology,Programming,Spring Boot,JPA,OneToMany,

In the One-To-Many association, we will first implement a unidirectional relationship, and then we will investigate the bidirectional relationship.

2. Spring Boot project creation

We will use Spring Initializr to create a new Spring Boot project, which will generate a basic structure for our Spring Boot project. The following dependencies have been added:
  • Spring Boot DevTools - necessary development tools  
  • Spring Web - for Spring MVC and embedded Tomcat that will run the Spring Boot application  
  • Spring Data JPA - Java Persistence API
  • MySQL Driver - JDBC driver for MySQL (for other DB you have to choose that dependency for that DB)
JAVA,Software Development,Hibernate,Technology,Programming,Spring Boot,JPA,OneToMany,
Then, to download the project zip file, click GENERATE. Unzip the zip archive. Import the project as a Maven project into Eclipse/STS.

3. Connect to the Database

We'll put the connection information in the application because we're using MySQL as our database. Hibernate will use this information to connect to the database as the application.properties file has a name/value pair. The connection information is described in the following snippet:
JAVA,Software Development,Hibernate,Technology,Programming,Spring Boot,JPA,OneToMany,

Here, we've set datasource.url to the URL of our JDBC connection. The database credentials are mentioned in datasource.user and datasource.password.

Spring Boot can gather the necessary information about the database from the connection URL, so it is not necessary to specify datasource.driver-class-name. However, we will be safer if we specify the driver-class-name.

When the application is running, jpa.show-sql displays Hibernate SQL queries in the console, jpa.hibernate.ddl-auto is set to update, which updates the database schema every time we restart the application, and hibernate.dialect indicates which database dialect we are using.


👉 We create two entities to demonstrate a unidirectional relationship in the One-To-Many association: Owner and Blog. We establish a One-To-Many relationship between these two entities by using the @OneToMany annotation.

4. Entities

Create a package called entity and create a Blog class with the following code snippet:
@Entity
@Table(name = "BLOG_DETAILS")
public class Blog {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "ID")
    private int id;

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

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

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

    public Blog() {}

    public Blog(String title, String category, String content) {
        this.title = title;
        this.category = category;
        this.content = content;
    }

    public int getId() { return id; }
    public void setId(int id) { this.id = id; }

    public String getTitle() { return title; }
    public void setTitle(String title) { this.title = title; }

    public String getCategory() { return category; }
    public void setCategory(String category) { this.category = category; }

    public String getContent() { return content; }
    public void setContent(String content) { this.content = content; }

    @Override
    public String toString() {
        return "Blog{" + "id=" + id + ", title='" + title + '\'' + ", category='" + category + '\'' +
                ", content='" + content + '\'' + '}';
    }
}
The Blog class has some private properties that have getter and setter methods, as well as a parameterized constructor and an overridden toString() method.

Create the Owner class in the entity package:
@Entity
@Table(name = "OWNER_DETAILS")
public class Owner {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "ID")
    private int id;

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

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

    @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinColumn(name = "blog_id")
    private List<Blog> blogList;

    public Owner() {}

    public Owner(String name, String email) {
        this.name = name;
        this.email = email;
    }

    public int getId() { return id; }
    public void setId(int id) { this.id = id; }

    public String getName() { return name; }
    public void setName(String name) { this.name = name; }

    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }

    public List<Blog> getBlogList() { return blogList; }
    public void setBlogList(List<Blog> blogList) { this.blogList = blogList; }

    @Override
    public String toString() {
        return "Owner{" + "id=" + id + ", name='" + name + '\'' + ", email='" + email + '\'' +
                ", blogList=" + blogList + '}';
    }
}
We declared a List of Blogs with the variable name blogList because one owner has many blogs. With the @OneToMany annotation, we are telling Hibernate to create a One-To-Many relationship between Owner and Blog and join them using the column name blog_id. As a result, Hibernate will create two tables, OWNER_DETAILS and BLOG_DETAILS (table names are mentioned in respective POJOs), and will modify table BLOG_DETAILS to add a foreign key (column name blog_id) that will be referenced by OWNER_DETAILS (column name id).

JAVA,Software Development,Hibernate,Technology,Programming,Spring Boot,JPA,OneToMany,

FetchType.LAZY will first load the main entity (Owner), then the related entity (Blog) on demand. 

5. Repositories

The repository in Spring Boot is the data access layer that allows us to interact with our real database for operations like insert, update, and delete using Spring Data JPA. We have significantly reduced the number of boilerplate codes required to perform database operations as our BlogRepository and OwnerRepository extend JpaRepository

Make a package called repository. Create a BlogRepository interface in it and include the following code snippet:
public interface BlogRepository extends JpaRepository<Blog, Integer> {
}

Create the OwnerRepository interface in the repository package:
public interface OwnerRepository extends JpaRepository<Owner,Integer> {
}

6. Controller

A controller is a class that has one or more public methods. Controllers are typically placed in the Controller directory. If a class is annotated with @Controller or @RestController in Spring Boot, it will serve as a controller, and its public methods will be exposed as HTTP endpoints if they are annotated with @PostMapping or @GetMapping

As a result, an HTTP GET request to http://localhost:PORT/method-name invokes the @GetMapping method of the ExampleController class.

The OwnerController has two methods: one to save the Owner with the Blog and the other to retrieve Owner details by id. We injected the OwnerRepository into our controller using the @Autowired annotation. The following is the code:
@RestController
@RequestMapping("/owner")
public class OwnerController {

    @Autowired
    private OwnerRepository ownerRepository;

    @PostMapping("/saveOwner")
    public Owner saveOwner(@RequestBody Owner owner) {
        System.out.println("Owner save called...");
        Owner ownerOut = ownerRepository.save(owner);
        System.out.println("Saved!!!");

        return ownerOut;
    }

    @GetMapping("/getOwner/{id}")
    public String getOwner(@PathVariable(name = "id") String id) {
        System.out.println("Owner get called...");
        Owner ownerOut = ownerRepository.getById(Integer.valueOf(id));
        System.out.println("\nOwner details with Blogs :: \n" + ownerOut);
        System.out.println("\nList of Blogs :: \n" + ownerOut.getBlogList());
        System.out.println("\nDone!!!");

        return "Owner fetched...";
    }
}

7. Run the Project

To run the project in Visual Studio Code, follow these steps:
  1. Open SpringbootmanytomanyApplication.java.
  2. Click on Run to run the Java program.
JAVA,Software Development,Hibernate,Technology,Programming,Spring Boot,JPA,OneToMany,

To run the project in Eclipse, follow these steps:
  1. Right-click on SpringbootmanytomanyApplication.java.
  2. Then choose Run As, then click on Spring Boot App.
JAVA,Software Development,Hibernate,Technology,Programming,Spring Boot,JPA,OneToMany,

Review the audit log in the console (Eclipse/VS Code) now: Hibernate created two tables for us - BLOG_DETAILS and OWNER_DETAILS - and modified the BLOG_DETAILS table to add the constraint Foreign key (owner_id) to set reference with the OWNER_DETAILS (ID) table. So we successfully mapped JAVA objects to database tables.

JAVA,Software Development,Hibernate,Technology,Programming,Spring Boot,JPA,OneToMany,

Because we did not specify a port in the application.properties file, our project will run on port 8080, and the default URL to access any REST API in this project is http://localhost:8080/. Because our project runs on our local machine, we used localhost. If your project is running on a remote server or in EC2, you must use the remote server's or EC2's IP address or the elastic IP address.

8. Testing of REST APIs

Now we will test those REST APIs that we have created in the OwnerController.

👉 Create a New Owner

To add a new Owner and his/her Blogs, enter the following URL into Postman:
http://localhost:8080/owner/saveOwner
JAVA,Software Development,Hibernate,Technology,Programming,Spring Boot,JPA,OneToMany,

Also, see the audit logs in the Console:
JAVA,Software Development,Hibernate,Technology,Programming,Spring Boot,JPA,OneToMany,
Hibernate first inserts Owner into the OWNER_DETAILS table, then Blogs into the BLOG_DETAILS table, and finally sets the OWNER_DETAILS table's ID column value in the blog_id columns of the BLOG_DETAILS table.

Let’s see the OWNER_DETAILS table:
JAVA,Software Development,Hibernate,Technology,Programming,Spring Boot,JPA,OneToMany,
And the BLOG_DEAILS table:
JAVA,Software Development,Hibernate,Technology,Programming,Spring Boot,JPA,OneToMany,

👉 Fetch Owner

To retrieve a specific Owner and his/her Blogs, we use Postman to call the following URL - we have passed the owner id as 1:
http://localhost:8080/owner/getOwner/1
JAVA,Software Development,Hibernate,Technology,Programming,Spring Boot,JPA,OneToMany,

And audit logs in the Console:
JAVA,Software Development,Hibernate,Technology,Programming,Spring Boot,JPA,OneToMany,
We have fetched a list of Blogs of an Owner.

9. Conclusion

Hooray!!! We successfully established a One-To-Many relationship. In the following tutorial, we will learn how to create a bidirectional One-To-Many relationship in Spring Boot using Hibernate.

You can download the source code.
Happy coding!!! 😊
in

No comments:

Post a Comment

Popular posts