1

I have tables Authors and Books (with join table Authorsbooks) in database. I created and initiated tables with MySQL. I have also made (a standard) JPA mapping with two entities Authors and Books using @manyToMany and @Jointable in one entity and mappedBy in the other and connected it to database.

When I try to get all members of Authors entity with Java with method findAll() it returns an endless sequence: like a first member of authors with list of books, in which a first Book contain list of Authors where it contain first Book which contain list of authors and so on, endless. How to get only authors w/o field listOfBooks (like I have it in the database table)?

@Entity

public class Author {

@Id
@GeneratedValue
@Column(name = "authorid")
private Integer authorid;

@Column(name = "authorname")
private String authorname;

@ManyToMany(fetch = FetchType.LAZY, mappedBy = "listOfAuthors")
private List<Book> listOfBooks = new ArrayList<Book>();
//getters and setters

@Entity

public class Book {

@Id
@GeneratedValue
@Column(name = "bookid")
private Integer bookid;
@Column(name = "bookname")
private String bookname;

@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "author2books", joinColumns = @JoinColumn(name = "bookid"),
        inverseJoinColumns = @JoinColumn(name = "authorid"))
private List<Author> listOfAuthors = new ArrayList<Author>();

//getters and setters

@RestController

@RequestMapping(value = "/rest/authors") public class AuthorResource {

@Autowired
AuthorsRepository authorsRepository;

@GetMapping(value = "/all")
public List<Author> getAll() {
    return authorsRepository.findAll();
}

}

CREATE TABLE author

( authorid INT AUTO_INCREMENT PRIMARY KEY, authorname VARCHAR(255) NOT NULL );

CREATE TABLE Book ( bookid INT AUTO_INCREMENT PRIMARY KEY, bookname VARCHAR(255) NOT NULL );

CREATE TABLE author2books ( authorid INT, bookid INT,

PRIMARY KEY (authorid, bookid), FOREIGN KEY (authorid) REFERENCES Author (authorid), FOREIGN KEY (bookid) REFERENCES Book (bookid) );

-- Create Author values INSERT INTO Author VALUES (authorid, 'Sven'); INSERT INTO Author VALUES (authorid, 'Peter');

-- Create Book values INSERT INTO Book VALUES (bookid, 'Biology'); INSERT INTO Book VALUES (bookid, 'Chemistry');

-- Create author2books values

INSERT INTO author2books VALUES (1, 2);

Entities mapping schema

Tables creation SQL script

Entities mapping/relationship

Database script

Nikzin
  • 322
  • 3
  • 20
  • _You_ might want to show your mapping, then _we_ might be able to help you spot the error. – Thomas Jan 12 '18 at 17:29
  • your probably triggering lazy loading after accessing a collection of `Author` type – Ramanlfc Jan 12 '18 at 17:29
  • Please don't post code snippets as images but rather as a code block (nicely formatted text). – Thomas Jan 12 '18 at 17:30
  • If you could please post the tables schema here too.. – Israel Merljak Jan 12 '18 at 17:38
  • 1
    You can take a look here also.. might help. https://stackoverflow.com/questions/33234546/spring-boot-jpa-onetomany-relationship-causes-infinite-loop – Israel Merljak Jan 12 '18 at 17:40
  • CREATE DATABASE testAuthor; USE testAuthor; CREATE TABLE Author ( authorid INT AUTO_INCREMENT PRIMARY KEY, authorname VARCHAR(255) NOT NULL ); CREATE TABLE Book ( bookid INT AUTO_INCREMENT PRIMARY KEY, bookname VARCHAR(255) NOT NULL ); CREATE TABLE author2books ( authorid INT, bookid INT, PRIMARY KEY (authorid, bookid), FOREIGN KEY (authorid) REFERENCES Author (authorid), FOREIGN KEY (bookid) REFERENCES Book (bookid) ); – Nikzin Jan 12 '18 at 17:57
  • I tried to add images with code. once it worked, another time it wasn't with an error "you need at least 10 points of reputation to add images". – Nikzin Jan 12 '18 at 18:14
  • @NikolayZ It's best if you actually post the written code when asking a question instead of an image so that we can easily copy/paste it for testing. Anyway.. have you seen the link i've mentioned in the comment before? The OP was having a similar problem and it was because he was referencing the relationship entity in a customized toString method, thus incurring in an infinite loop when loading the entities. Please review your code for possible changes like that, and/or post it here so that we can help you find the problem. – Israel Merljak Jan 12 '18 at 19:34
  • @Israel Merljak Added code. and somebody allowed my pictures. – Nikzin Jan 12 '18 at 20:57

2 Answers2

1

I was surprised that there was not easy to find a solution for this in my opinion standard situation. I found two ways to solve it. The first is a bit indirect: Making a query returning entity without including ManytoMany list field like described here:Spring JPA selecting specific columns. Second way is more direct but looks quite exotic: using JsonBackReference and JsonManagedReference annotations like here: https://www.keenformatics.com/how-to-solve-json-infinite-recursion/

Kurt Bourbaki
  • 11,984
  • 6
  • 35
  • 53
Nikzin
  • 322
  • 3
  • 20
0

You can try to mark the relationship Book -> author / Author -> book Lazy loaded to avoid entering an infinite loop :)

@ManyToMany(fetch = LAZY)

Israel Merljak
  • 241
  • 3
  • 9
  • that's probably reduntant bcoz entity relationships involving collections are by default lazy loaded – Ramanlfc Jan 12 '18 at 17:30
  • Yeah you're right. it is the default way, but it can't hurt to try right? His mapping doesn't seem to be the problem here anyways. Or perhaps it is.. – Israel Merljak Jan 12 '18 at 17:35
  • Thank you, I tried: but no changes: an infinite loop. – Nikzin Jan 12 '18 at 18:03
  • 1
    After long time searching for the answer in Google and Stackoverflow I found one which actually helped. But I don't know if that may give side effects: using JsonBackReference and JsonManagedReference annotations like here: http://keenformatics.blogspot.se/2013/08/how-to-solve-json-infinite-recursion.html . Maybe there is another way. I need to test those annotations. – Nikzin Jan 12 '18 at 23:39