Hibernate Relationship Tutorial – @OneToMany and @ManyToOne (Part 8 to 12)

Hibernate Tutorial Part 8 to 12

First let me say that if you have gotten to this point successfully, congrats! and thumbs up to you! You’ll sure be an expert if you keep this pace and don’t give up!

We would continue with the Hibernate Relationship tutorial. We’ll cover the following:

Pay attention to how to solve the problem of Infinite recursion.

This is Part 1 to 7

 

Part 8 – @JoinColumn Annotation

The @JoinColumn annotation is used to specify the actual column(in the table) used for the mapping. This is done at the entity that owns the mapping.

In the case of User-Post relationship, the Post owns the relationship and automatically creates the user_id column. This is the JoinColumn.

Similarly, the  Location-User relationship, the Location owns the relationship and provides the location_id column.

Follow the steps below to add the @JoinColumn annotation

Step 1: In the Location field of the User entity, add @JoinColumn(name=”location_id”)

Step 2: In the User field of the Post entity, add @JoinColumn(name=”user_id”)

Step 3: Relaunch and check the tables in the h2 console (nothing changes though!)

 

Part 9 – Setup findAll() and findById() for all Entities

Write the methods to in the RestController files for Post, User and Location.

(You should be able to do this by now, else, watch the video and follow along)

The three RestController and Services files would contain the following:

UserController

@Autowired
private UserService userService;

@GetMapping("/users")
public List<User> getAllUsers() {
    return userService.findAll();
}

@GetMapping("/users/{id}")
public Optional<User> getUserById(@PathVariable Integer id) {
    return userService.findById(id);
}

 

UserService

@Autowired
private UserRepository userRepository;

public List<User> getAllUsers() {
	return (List<User>) userRepository.findAll();
}

public Optional<User> getUserById(Integer id) {
	return userRepository.findById(id);
}

 

Step 1: Launch the application and visit http://localhost/users to see the list of users.

 

LocationController

@Autowired
private LocationService locationService;
	
@GetMapping("/locations")
public List<Location> getAllLocations() {
	return locationService.findAll();
}
	
@GetMapping("/locations/{id}")
public Optional<Location> getLocationById(@PathVariable Integer id) {
	return locationService.findById(id);
}

 

LocationService

@Autowired
private LocationRepository locationRepository; 

public List<Location> findAll() {
	return (List<Location>) locationRepository.findAll();
}

public Optional<Location> findById(Integer id) {
	return locationRepository.findById(id);
}

 

PostController

@Autowired
private PostService postService;

@GetMapping("/posts")
public List<Post> getAllPosts() {
    return postService.findAll();
}

@GetMapping("/posts/{id}")
public Optional<Post> getPostById(@PathVariable Integer id) {
    return postService.findById(id);
}

 

PostService

private PostRepository postRepository;

public List<Post> findAll() {
	return (List<Post>) postRepository.findAll();
}

public Optional<Post> findById(Integer id) {
	return postRepository.findById(id);
}

 

Part 10 – Infinite Recursion (StackOverflow Error)

We would now solve a problem that always arises when you have mapping between entities. Let’s see what the problem is first!

Step 1: In the User entity, right-click and generate Getter and Setters for the posts field

Step 2: In the Location entity, right-click and generate Getter and Setter for the users field

Step 3: Relaunch the application. Try to access the list of users via http://localhost:8080/users. You will notice, that it produces an infinite number of items. In you look at the console, you will now see this error.

Let’s solve it!

 

Part 11- Solving Infinite Recursion using @JsonManagedReference and @JsonBackReference

So we need a way to break the infinite recursion loop. The @JsonManagedReference is used on the OneToMany side while the @JsonBackReference is used at the @ManyToOne side.

@JsonManagedReference is the forward part of the mapping/reference and the data gets serialized normally.

@JsonBackReference is is the backward side of the mapping and the data  does not get serialized

Follow the steps below:

Step 1: Add @JsonManagedReference to the getPosts method in the User entity

Step 2: Add @JsonBackReference to the getUser method of the Post entity

Step 3: Add @JsonManagedReference to the getUsers method of the Location entity

Step 4: Add @JsonBackReference to the getLocation method of the User entity

Step 5: Relaunch the application, try to access list of Users, Locations, or Posts. Notice that the problem is solved

Other methods of handling this problem include use of @JsonIdentityInfo and JsonIgnore annotations. These are discussed below

 

Part 12 – @JsonIdentifyInfo and @JsonIgnore

Now, the @JsonIgnore is an alternative  for the @JsonBackReference. So you can used @JsonIgnore in place of @JsonBackReference

@JsonIdentityInfo can be used in place of the both @JsonManagedReference and @JsonBackReference. However, the @JsonIdentityInfo annotation is added to the class and NOT to the methods. Also, the @JsonIdentityInfo requires some attributes as shown in the code below:

 

@JsonIdentityInfo(
	generator = ObjectIdGenerators.PropertyGenerator.class, 
	property = "id")

 

If you have gotten to this point successfully, congrats! and thumbs up to you! You’ll sure be an expert if you keep this pace and don’t give up. Feel free to watch the videos and if you have challenges, mention it in the comment box either below this page or below the video.

Now, on to the next Part!

4 Comments on “Hibernate Relationship Tutorial – @OneToMany and @ManyToOne (Part 8 to 12)”

Leave a Reply

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