Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hibernate FETCH.Eager fetching duplicates when using Spring Data repositories

I am facing an issue with Spring Data repository + Hibernate (in spring 2.1.4)

Note: Everything was working fine in spring 1.5.x

The problem is with @ManyToOne(fetch = FetchType.Lazy) I get correct records in 1.5 but error in spring 2.0 but with @ManyToOne(fetch = FetchType.Eager) I get duplicate records in List<Stories>.

I am using Spring data repositories epicRepository.findById(Long id) (previously Spring had epicRepository.find() but they removed it in spring 2.x)

I don't want to use @Fetch (FetchMode.SELECT) solution as it has to execute multiple select queries and will become very non-performant.

Problem:

  1. if I use fetch = FetchType.Lazy i am getting an error could not initialize proxy - no session (only started after upgrading to spring 2.x and returned correct number of rows) [This error seems to be ok as I am trying to fetch the list.count later in the code, and there are no duplicates when I checked through debugger before the erroring line]
  2. so based on some solutions here in SO I used FetchType.Eager (I understand the performance implications of this, but anyway I needed to do this for another work so I did this because this list is smaller and need to preserve some business logic during updates). But Now I am getting duplicate records.

Even If what I do is wrong, the count in list (mean the duplicates) should not be wrong ?

I have the following JPA entities / tables

  1. Epic -> [id (pk), name, status_id (fk))
  2. Story->[id (pk), name, status_id (fk), epic_id (fk))
  3. Task -> [id (pk), name, resolution_type_id (fk), story_id (fk))

forgive me if there any typos (as i recreated code manually using different use case)

Epic.java

@Data
public class Epic {

  @Id
  private Long id;
  private String name;
  @OneToOne(fetch = FetchType.Eager, optional = false)
  @JoinColumn(name = id, referenceColumnName = 'id', nullable = false, insertable = true, updatable = true)
  private Status status;
   @OneToMany(fetch = FetchType.Eager, cascade = ALL, mappedBy = epic)
  private List<Story> stories;
}

Story.java

@Data
public class Story {

  @Id
  private Long id;
  private String name;
  @OneToOne(fetch = FetchType.Eager, optional = false)
  @JoinColumn(name = id, referenceColumnName = 'id', nullable = false, insertable = true, updatable = true)
  private Status status;
   @OneToMany(fetch = FetchType.Eager, cascade = ALL, mappedBy = epic)
  private List<Task> tasks;

  @ManyToOne(fetch = FetchType.Lazy)
  // This is the problem area
  // Error if FetchType.Eager 
  // But duplicates in FetchType.Lazy
  @JoinColumn(name = "id", nullable = false) 
  private Epic epic;
}

Task.java

@Data
public class Task {
  @Id
  private Long id;
  private String name;
  @ManyToOne(fetch = FetchType.Lazy)
  @JoinColumn(name = "id")
  private Story story;
  @OneToOne (fetch = FetchType.Eager, optional = true)
  @JoinColumn (name = "id", )
  private Resolution resolution;
}
like image 276
Dexters Avatar asked Dec 07 '25 04:12

Dexters


1 Answers

This question has been replied to many times before. Your options could be:

  • all EAGER collections you should migrate to Sets
  • manually do duplicate filtering using stream.distinct.collect on getters of collections.
like image 77
Rade_303 Avatar answered Dec 08 '25 17:12

Rade_303