Hibernate OneToMany Relationship is one of the most used relationship when we do coding l, as why i am saying this is that , most of the scenario and use cases have the situation where we have one entity related with many other entity.
before we start taking about OneToMany using JPA , would like to cover the question what is OnetoMany Relationship in Hibernate.
Also read : OneToOne Hibernate Relationship
OneToMany Relationship : When one entity ( table) is assotiated with more than one other entity (tables) , It is called OneToMany Mapping
Mapping can be
Unidirectional : One Way Directional
Bidirectional : Both Way Directional.
In this article we will see how we implement One To Many Mapping Unidirectional with JPA in Spring Boot.
Let start.
First we will discuss the Scenario then we will talk about the Solution.
#Scenario
We are having 2 entity as vendor and ratings , We need to establish a relationship between vendor and ratings as OneToMany Unidirectional
#Solution
In this use case ratings itself dont have any importance if there is no vendor associated with it , that means if we are deleting the vendors , ratings should also be deleted associated to particular vendor.
this is called as one to many unidirectional mapping.
Now let see the Implementation.
Implementation (You can download the project from GitHub)
We will have one Rest End point where we are saving the vendor along with the rating of the vendor.
We are using below dependencies
1) Spring Web ( For Rest APIs )
2) H2 Database ( For InMemory Database)
3) JPA ( As ORM )
* can see the pom.xml in above github link
We will first see the Models used here
Vendor.java
Now we will see the other entity used in this use case
Rating.java
We will use POSTMAN to hit the rest endpoint with below RequestBody
{
"name": "vendor1",
"companyName": "programinjava",
"ratings": [
{
"rating": 4,
"comment": "the vendor is ok ok "
}
]
}
Important Things :
#Solution
In this use case ratings itself dont have any importance if there is no vendor associated with it , that means if we are deleting the vendors , ratings should also be deleted associated to particular vendor.
this is called as one to many unidirectional mapping.
Now let see the Implementation.
Implementation (You can download the project from GitHub)
We will have one Rest End point where we are saving the vendor along with the rating of the vendor.
We are using below dependencies
1) Spring Web ( For Rest APIs )
2) H2 Database ( For InMemory Database)
3) JPA ( As ORM )
* can see the pom.xml in above github link
We will first see the Models used here
Vendor.java
package com.programinjava.learn.model; import java.util.ArrayList; import java.util.List; import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.OneToMany; @Entity public class Vendor { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private Integer id; private String name; private String companyName; // other attributes of vendors @OneToMany(cascade=CascadeType.ALL) @JoinColumn(name="vendor_id") private List<Rating> ratings = new ArrayList<>(); public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getCompanyName() { return companyName; } public void setCompanyName(String companyName) { this.companyName = companyName; } public List<Rating> getRatings() { return ratings; } public void setRatings(List<Rating> ratings) { this.ratings = ratings; } }
Rating.java
package com.programinjava.learn.model; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; @Entity public class Rating { @Id @GeneratedValue(strategy=GenerationType.AUTO) private Integer id; private Integer rating; private String comment; public Rating() { // TODO Auto-generated constructor stub } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Integer getRating() { return rating; } public void setRating(Integer rating) { this.rating = rating; } public String getComment() { return comment; } public void setComment(String comment) { this.comment = comment; } }
If we see the Database schema generated for the above entity.
Now we will see the service Impl Class.
VendorServiceImpl.java
VendorController.java
Now when we see the Rest Endpoint Exposed is http://localhost/vendor ( which is post type )
Vendor Table
Rating Table
VendorServiceImpl.java
package com.programinjava.learn.service; import java.util.ArrayList; import java.util.List; import java.util.Optional; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.programinjava.learn.model.Rating; import com.programinjava.learn.model.Vendor; import com.programinjava.learn.repository.VendorRepository; @Service public class VendorServiceImpl implements VendorService{ @Autowired VendorRepository vendorRepository; @Override public int add(Vendor vendor) throws Exception { Vendor vendor1 =vendorRepository.save(vendor); if(vendor1 == null) throw new Exception("Vendor not saved"); return vendor1.getId(); } @Override public void getAll() { // TODO Auto-generated method stub } @Override public void provideRating(Rating rating, Integer vendorId) throws Exception { if(vendorId !=null) { Optional<Vendor> vendor1 =vendorRepository.findById(vendorId); if(vendor1 == null) throw new Exception("Vendor not found"); Vendor ve =vendor1.get(); ve.getRatings().add(rating); } } }
package com.programinjava.learn.controller; import java.net.URI; import javax.servlet.http.HttpServletRequest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.util.UriTemplate; import com.programinjava.learn.model.Vendor; import com.programinjava.learn.service.VendorService; @RestController public class VendorController { @Autowired VendorService vendorService; @PostMapping("/vendor") public ResponseEntity<Void> addVendor(@RequestBody Vendor vendor,BindingResult errors , HttpServletRequest request){ if(errors.hasErrors()) { return ResponseEntity.badRequest().build(); } try { Integer id =vendorService.add(vendor); URI location = new UriTemplate(request.getRequestURI() + "/{id}").expand(id); return ResponseEntity.created(location).build(); } catch (Exception e) { // TODO Auto-generated catch block return ResponseEntity.badRequest().build(); } } @GetMapping("/ping") public String ping() { return "Pong"; } }
We will use POSTMAN to hit the rest endpoint with below RequestBody
{
"name": "vendor1",
"companyName": "programinjava",
"ratings": [
{
"rating": 4,
"comment": "the vendor is ok ok "
}
]
}
Important Things :
- The Rating table don't have any vendor_id column defination ( if you have checked ).
- If Vendor is deleted , the ratings of the vendor will also be deleted from the table.
- We can fetch the rating wrt vendor but we can't fetch the vendor wrt rating as it is Unidirectional Mapping.
I hope this article will help you in understanding OneToMany relationship in hibernate using spring boot and JPA.
Thanks for reading
0 comments:
Post a Comment