micronaut-projects / micronaut-projects/micronaut-data
@EntityGraph doesn't work in some cases.
- Dominant language
- Java
- Stars
- 482
- Forks
- 229
- Avg merge
- 1d 7h
- Merged PRs (30d)
- 32
Description
Hi,
It seems like `@EntityGraph` annotation is just ignored in some cases, especially for methods without arguments like `findAll()` or `list()` and also in a conjunction with spring `Specification`.
At the same time `@Join` works fine for `findAll()` with no arguments and doesn't work for `findAll(Specification spec)`.
### Task List
- [x] Steps to reproduce provided
- [ ] Stacktrace (if present) provided
- [ ] Example that reproduces the problem uploaded to Github
- [x] Full description of the issue provided (see below)
### Steps to Reproduce
1. Create two simple entities with `@ManyToOne` relation:
```
@Entity
@Table(name = "portal.book")
public class Book {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NotNull
private String title;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "author_id")
private Author author;
}
@Entity
@Table(name = "portal.author")
public class Author {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NotNull
private String name;
}
```
2. Define repository:
```
@Repository
@Transactional
public interface BookRepository extends CrudRepository {
@Override
@EntityGraph(attributePaths = {"author"})
List findAll();
// or
@EntityGraph(attributePaths = {"author"})
List listAll();
}
```
### Expected Behaviour
Author must be eagerly fetched according to the `@EntityGraph` annotation in order to avoid n+1 query:
```
DEBUG org.hibernate.SQL - select book0_.id as id1_3_0_, author1_.id as id1_2_1_, book0_.author_id as author_i3_3_0_, book0_.title as title2_3_0_, author1_.name as name2_2_1_ from portal.book book0_ inner join portal.author author1_ on book0_.author_id=author1_.id
```
### Actual Behaviour
Author is not eagerly fetched. Addition query is executed:
```
DEBUG org.hibernate.SQL - select book0_.id as id1_3_, book0_.author_id as author_i3_3_, book0_.title as title2_3_ from portal.book book0_
DEBUG org.hibernate.SQL - select author0_.id as id1_2_0_, author0_.name as name2_2_0_ from portal.author author0_ where author0_.id=?
```
### Environment Information
- **Micronaut Version:** 2.2.3
- **JDK Version:** 1.8
Some more test cases:
```
@Repository
@Transactional
public interface BookRepository extends CrudRepository {
@Override
@EntityGraph(attributePaths = {"author"})
List findAll();
// ^ X. Doesn't work. Causes n+1 additional query
@Override
@Join(value = "author", type = Join.Type.FETCH)
List findAll();
// ^ V. Works fine!
@EntityGraph(attributePaths = {"author"})
List findAll(Specification spec);
// ^ X. Doesn't work. Causes n+1 additional query
@Join(value = "author", type = Join.Type.FETCH)
List findAll(Specification spec);
// ^ X. Doesn't work. Causes n+1 additional query
@EntityGraph(attributePaths = {"author"})
Page findAll(Specification spec, io.micronaut.data.model.Pageable pageable);
// ^ X. Doesn't compile. Causes: Unable to implement Repository method: BookRepository.findAll(Specification spec, Pageable pageable). Cannot query entity [Book] on non-existent property: spec
@EntityGraph(attributePaths = {"author"})
Page findAll(Specification spec, org.springframework.data.domain.Pageable pageable);
// ^ X. Compiles but causes n+1 additional query
@Join(value = "author", type = Join.Type.FETCH)
Page findAll(Specification spec, org.springframework.data.domain.Pageable pageable);
// ^ X. Compiles but causes n+1 additional query
@EntityGraph(attributePaths = {"author"})
List findByTitle(String title);
// ^ V. Works fine in all cases when there is at least 1 input parameter!!!
}
```
Contributor guide
Research direction
Start with the repository method handling for @EntityGraph, especially the BookRepository cases using findAll() and Specification, and reproduce the generated SQL described in the issue. Trace how no-argument and Specification methods are processed; done means the author relation is eagerly fetched without the reported n+1 queries and the pageable cases behave consistently.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java, spring
- Domain
- backend, databases
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100