Hibernate Relationship Tutorial – @OneToMany and @ManyToOne (Part 21 to 28 )

We would continue from Part 21. You will learn how to update a record and delete a record. You will also learn about CascadeTypes and FetchTypes in Hibernate. So let’s get stated!

 

Part 21 – Updating Location Details

To update Location details, follows the steps below:

Step 1: Open the LocationController file

Step 2: Copy and paste the code below

@PutMapping("/location/{id}/update")
public void UpdateLocation(@RequestBody Location location) {
	locationService.UpdateLocation(location);
}

 

Step 3: Open the LocationService and paste the code below:

public void UpdateLocation(Location location) {
	locationRepository.save(location);
}

 

Step 4: Launch the application. Use Advanced REST Client to attempt to update a location. Set the method this time to PUT

 

Part 22 – Updating User Details

To update Location details, follows the steps below:

Step 1: Open the UserController file

Step 2: Copy and paste the code below

@PutMapping("/user/{id}/update")
public void UpdateUsern(@RequestBody User user ) {
	userService.UpdateUser(user);
}

 

Step 3: Open the UserService and paste the code below:

public void UpdateUser(User user) {
	userRepository.save(user);
}

 

Step 4: Relaunch and test

 

Part 23 – Updating Post Details

To update Location details, follows the steps below:

Step 1: Open the PostController file

Step 2: Copy and paste the code below

@PutMapping("/post/{id}/update")
public void UpdatePost(@RequestBody Post post) {
	postService.UpdatePost(post);
}

 

Step 3: Open the PostService and paste the code below:

public void UpdatePost(Post post) {
	postRepository.save(post);
}

 

Step 4: Relaunch and test

 

Part 24: Deleting a Post

Deleting a Post would be quite straightforward as the Post object does not have any child objects. So let’s get it done!

Step 1: Copy the code below and paste in the PostController

@DeleteMapping("/post/{id}/delete")
public void DeletePost(@PathVariable Integer id) {
     postService.DeletePost(id);
}

 

Step 2: Copy the code below and paste into the PostService

public void DeletePost(Integer id) {
    postRepository.deleteById(id);
}

 

Step 3: Relaunch the application and test it using r the REST client. Either way, check that the post was deleted using H2 Console.

 

Part 25: Deleting a User

The question about deleting a User is this: If we delete a particular user, what will happen to all the posts belonging to this user? Well, before we answer this question, let’s try to delete a user using the method used in deleting post.

Step 1: Copy the code below and paste in the UserController

@DeleteMapping("/user/{id}/delete")
public void DeleteUser(@PathVariable Integer id) {
     userService.DeleteUser(id);
}

 

Step 2: Copy the code below and paste into the UserService

public void DeleteUser(Integer id) {
    userRepository.deleteById(id);
}

 

Step 3: Relaunch the application and test it using  REST client. Try to delete user/1. You will notice that the delete operation fails. You receive a message like:

{
"timestamp": "2019-09-02T22:23:30.879+0000",
"status": 500,
"error": "Internal Server Error",
"message": "could not execute statement; SQL [n/a]; constraint ["FK2SF14YOUCWQSO9PDCH0UIWPEM: PUBLIC.POST FOREIGN KEY(USERID) REFERENCES PUBLIC.USER(ID) (1)"; SQL statement: delete from user where id=? [23503-199]]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement",
"path": "/user/1/delete"
}

 

The reason for this error is that we try to delete a user who has posts.( an entity with child entities)

Let’s now solve this problem by talking about CascadeTypes

 

Part 26: CascadeType in Hibernate

The CascadeType answers the question of what will happen when you delete an object has children reference objects. Now a number of things could happen

  • CascadeType.REMOVE: All the child entities are deleted (all post for the user is deleted)
  • CascadeType.ALL: In this case, the operation is propagated from the parent to all the child entities
  • CasCadeType.MERGE: It propagates merge operation from the parent to the child entities
  • CascadeType.PERSIST: Here, the transient instance is made persistent
  • CascadeType.DETACH: This cascade type removes that entity from the persistent context.

Let’s not go to far! We’ll only use the second one: CascadeType.ALL

To solve the problem simply take the step below:

Step 1: Open the User model

Step 2: Add cascade = CascadeType.ALL  to the @OneToMany annotation. It would be as shown below:

@OneToMany(mappedBy="user", cascade = CascadeType.ALL)
private List<Post> posts;

 

Step 3: Now try to repeat the delete operation and see that it works!

 

Exercise: As an exercise for you, try out other CascadeTypes. Let me know in the comment box below the outcome

 

Part 27 – Deleting a Location

This follows for the method for deleting a user.

Step 1: Copy the code below and paste in the LocationController

@DeleteMapping("/location/{id}/delete")
public void DeleteLocation(@PathVariable Integer id) {
     locationService.DeleteLocation(id);
}

 

Step 2: Copy the code below and paste into the LocationService

public void DeleteLocation(Integer id) {
    locationRepository.deleteById(id);
}

 

Step 2: Open the User model, Add cascade = CascadeType.ALL  to the @OneToMany annotation. It would be as shown below:

@OneToMany(mappedBy="location", cascade = CascadeType.ALL)
private List<User> users;

 

Step 3: Relaunch and try deleting a location. It works too.

 

Part 28: FetchType in Hibernate

I would like to wrap up this course by talking about FetchTypes. This relates to how data is pulled from the repository – essentially from the database.

We would focus on two types of FetchTypes: FetchType.EAGER and FetchType.LAZY

FetchType.EAGER: This FetchType tells hibernate to retrieve the related record along with the initial query. This can be an advantage, but when the child entities to fetch is much, then it could create an overhead can jeopardize performance. For example, having to retrieve all the users in a location each time to access a Location.

FetchType.LAZY: This can be used to tell hibernate to delay the initialization of the mapping until you access it explicitly.

Do the following exercise:

  • Exercise 1: Add fetchType= FetchType.EAGER to all the @ManyToOne annotation
  • Exercise 2: Add fetchType=FetchType.LAZY  to all the @OneToMany annotations
  • Exercise 3: Test the application with the FetchTypes.
  • Exercise 4: Remove all the FetchTypes and test the application again. Did you observe any change. Mention it in the comment box below.

 

Finally you made it to the end of this course. Thumbs up to you!

User Avatar

kindsonthegenius

Kindson Munonye is currently completing his doctoral program in Software Engineering in Budapest University of Technology and Economics

View all posts by kindsonthegenius →

4 thoughts on “Hibernate Relationship Tutorial – @OneToMany and @ManyToOne (Part 21 to 28 )

  1. If we use
    cascade = CascadeType.ALL, fetch = FetchType.LAZY
    for @OneToMany relations it allows us to delete entities with child entity.

  2. I realized I was wrong, cascade = CascadeType.ALL will delete children entities …

    If I understood correctly
    LAZY and EAGER refers to loading data, I googled a bit and realized the difference, for example one user has more posts, if the fetch type is LAZY when reading from the user database, his posts will not be displayed unless we call the getPosts () method

Leave a Reply

Your email address will not be published. Required fields are marked *