Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Boot JPA - OneToMany relationship causes infinite loop

I have a two objects with simple @OneToMany relationship which looks as follows:

parent:

@Entity
public class ParentAccount {

  @Id
  @GeneratedValue
  private long id;
  private String name;

  @OneToMany(fetch = FetchType.EAGER, mappedBy = "parentAccount")
  private Set<LinkedAccount> linkedAccounts;

}

child:

@Entity
public class LinkedAccount {

  @Id
  @GeneratedValue
  private long id;

  @ManyToOne(optional = false)
  private ParentAccount parentAccount;

  private String name;

  // empty constructor for JPA
  public LinkedAccount() {
  }

}

I ma using Spring CrudRepository to operate with these entities. However, when calling ParentAccount parent = parentAccountRepository.findOne(id);, some kind of infinite loop starts happening and hibernate spams this all over the console:

Hibernate: select linkedacco0_.parent_account_id as parent_a6_1_0_, linkedacco0_.id as id1_0_0_, linkedacco0_.id as id1_0_1_, linkedacco0_.aws_id as aws_id2_0_1_, linkedacco0_.key_id as key_id3_0_1_, linkedacco0_.name as name4_0_1_, linkedacco0_.parent_account_id as parent_a6_0_1_, linkedacco0_.secret_key as secret_k5_0_1_ from linked_account linkedacco0_ where linkedacco0_.parent_account_id=?

I tried changed the fetch type to LAZY but then I get this error:

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.berrycloud.scheduler.model.ParentAccount.linkedAccounts, could not initialize proxy - no Session

(It seems that it is trying to do the lazy load outside of the transactional context).

This is my CRUD repository:

@Repository
public interface ParentAccountRepository extends CrudRepository<ParentAccount, Long> {
}

Could someone tell me how to resolve this issue? I would prefer the solution with EAGER fetch. Thank you for any tips

EDIT: here is the schema I am using

CREATE TABLE parent_account (
    id BIGINT auto_increment,
    name VARCHAR(80) null,
    PRIMARY KEY (`id`)
);

CREATE TABLE linked_account (
    id BIGINT auto_increment,
    parent_account_id BIGINT,
    name VARCHAR(80) null,
    FOREIGN KEY (`parent_account_id`) REFERENCES `parent_account` (`id`),
    PRIMARY KEY (`id`)
);
like image 943
Smajl Avatar asked Oct 20 '15 10:10

Smajl


2 Answers

As the first answer suggests:

Do not use Lombok's @Data annotation on @Entity classes.

Reason: @Data generates hashcode(), equals() and toString() methods that use the generated getters. Using the getter means of course fetching new data even if the property was marked with FetchType=LAZY.

Somewhere along the way hibernate tries to log the data with toString() and it crashes.

like image 134
user1819111 Avatar answered Sep 22 '22 20:09

user1819111


Problem solved. I was using a custom @toString method in the LinkedAccount which was referencing the ParentAccount. I had no idea that this could cause any problem and therefor I did not include the toString in my question.

Apparently, this was causing an infinite loop of lazy loading and removing this reference fixed the problem.

like image 22
Smajl Avatar answered Sep 23 '22 20:09

Smajl