FETCH TYPE COMPORTAMENT #99
-
Hello, I have a question about SQL construction... @OneToMany(mappedBy = "estabelecimento", fetch = FetchType.LAZY)
@Fetch(FetchMode.SELECT)
private Set<Produto> produtos;
@Transactional(readOnly = true)
public Page<EstabelecimentoVO> findAll(
Predicate predicate,
Pageable pageable,
List<String> expand
) {
return estabelecimentoRepository.findAll(
predicate,
pageable,
new DynamicEntityGraph(EntityGraphType.LOAD, expand)
).map(estabelecimentoMapper::toDTO);
} Request Output {
"content": [
{
"id": 1,
"nome": "Estab 001",
"nomeCompleto": "Estabelecimento 001",
"razaoSocial": "Estabelecimento 001",
"cnpj": "111111",
"logoUrl": null,
"gestor": null,
"enderecos": null,
"produtos": null
}
],
"pageable": {
"sort": {
"empty": true,
"sorted": false,
"unsorted": true
},
"offset": 0,
"pageNumber": 0,
"pageSize": 1,
"paged": true,
"unpaged": false
},
"last": false,
"totalPages": 25,
"totalElements": 25,
"first": true,
"size": 1,
"number": 0,
"sort": {
"empty": true,
"sorted": false,
"unsorted": true
},
"numberOfElements": 1,
"empty": false
} SQL Hibernate Hibernate:
select
e1_0.id,
e1_0.cnpj,
e1_0.gestor_id,
e1_0.logo_url,
e1_0.nome,
e1_0.nome_completo,
e1_0.razao_social
from
estabelecimento e1_0 offset ? rows fetch first ? rows only
Hibernate:
select
count(e1_0.id)
from
estabelecimento e1_0 That way apparently it's ok, but when I use "expand" to expand the child products it ends up applying the offset in the join Request Output {
"content": [
{
"id": 1,
"nome": "Estab 001",
"nomeCompleto": "Estabelecimento 001",
"razaoSocial": "Estabelecimento 001",
"cnpj": "111111",
"logoUrl": null,
"gestor": null,
"enderecos": null,
"produtos": [
{
"id": 1,
"nome": "Produto 001",
"descricao": "Produto 001",
"preco": 233.22,
"imagemUrl": "https://loremflickr.com/640/480/product",
"estabelecimento": null,
"imagens": [
{
"id": 1,
"url": "https://loremflickr.com/640/480/product"
},
{
"id": 2,
"url": "https://loremflickr.com/640/480/product"
}
],
"categorias": [
{
"id": 1,
"descricao": "Moda",
"icone": null
},
{
"id": 2,
"descricao": "Mercado",
"icone": null
}
]
}
]
}
],
"pageable": {
"sort": {
"empty": true,
"sorted": false,
"unsorted": true
},
"offset": 0,
"pageNumber": 0,
"pageSize": 1,
"paged": true,
"unpaged": false
},
"last": false,
"totalPages": 25,
"totalElements": 25,
"first": true,
"size": 1,
"number": 0,
"sort": {
"empty": true,
"sorted": false,
"unsorted": true
},
"numberOfElements": 1,
"empty": false
} SQL Hibernate Hibernate:
select
e1_0.id,
e1_0.cnpj,
e1_0.gestor_id,
e1_0.logo_url,
e1_0.nome,
e1_0.nome_completo,
p1_0.estabelecimento_id,
p1_0.id,
p1_0.descricao,
p1_0.imagem_url,
p1_0.nome,
p1_0.preco,
e1_0.razao_social
from
estabelecimento e1_0
left join
produto p1_0
on e1_0.id=p1_0.estabelecimento_id offset ? rows fetch first ? rows only The problem part would be applying pagination to the left join left join
produto p1_0
on e1_0.id=p1_0.estabelecimento_id offset ? rows fetch first ? rows only Because if I run it with separate queries, it doesn't limit the number of children. Something like... {
"content": [
{
"id": 1,
"nome": "Estab 001",
"nomeCompleto": "Estabelecimento 001",
"razaoSocial": "Estabelecimento 001",
"cnpj": "111111",
"logoUrl": null,
"gestor": null,
"enderecos": null,
"produtos": [
{
"id": 24,
"nome": "Produto 024",
"descricao": "Produto 024",
"preco": 3333.33,
"imagemUrl": "https://loremflickr.com/640/480/product",
"estabelecimento": null,
"imagens": [],
"categorias": []
},
{
"id": 43,
"nome": "Produto 043",
"descricao": "Produto 043",
"preco": 3333.33,
"imagemUrl": "https://loremflickr.com/640/480/product",
"estabelecimento": null,
"imagens": [],
"categorias": []
},
{
"id": 36,
"nome": "Produto 036",
"descricao": "Produto 036",
"preco": 3333.33,
"imagemUrl": "https://loremflickr.com/640/480/product",
"estabelecimento": null,
"imagens": [],
"categorias": []
},
{
"id": 2,
"nome": "Produto 002",
"descricao": "Produto 002",
"preco": 111.11,
"imagemUrl": "https://loremflickr.com/640/480/product",
"estabelecimento": null,
"imagens": [
{
"id": 3,
"url": "https://loremflickr.com/640/480/product"
},
{
"id": 4,
"url": "https://loremflickr.com/640/480/product"
}
],
"categorias": [
{
"id": 2,
"descricao": "Mercado",
"icone": null
}
]
},
{
"id": 38,
"nome": "Produto 038",
"descricao": "Produto 038",
"preco": 3333.33,
"imagemUrl": "https://loremflickr.com/640/480/product",
"estabelecimento": null,
"imagens": [],
"categorias": []
},
{
"id": 32,
"nome": "Produto 032",
"descricao": "Produto 032",
"preco": 3333.33,
"imagemUrl": "https://loremflickr.com/640/480/product",
"estabelecimento": null,
"imagens": [],
"categorias": []
},
{
"id": 8,
"nome": "Produto 008",
"descricao": "Produto 008",
"preco": 777.77,
"imagemUrl": "https://loremflickr.com/640/480/product",
"estabelecimento": null,
"imagens": [
{
"id": 15,
"url": "https://loremflickr.com/640/480/product"
},
{
"id": 16,
"url": "https://loremflickr.com/640/480/product"
}
],
"categorias": [
{
"id": 8,
"descricao": "Ferramentas",
"icone": null
}
]
},
{
"id": 15,
"nome": "Produto 015",
"descricao": "Produto 015",
"preco": 3333.33,
"imagemUrl": "https://loremflickr.com/640/480/product",
"estabelecimento": null,
"imagens": [],
"categorias": []
},
{
"id": 33,
"nome": "Produto 033",
"descricao": "Produto 033",
"preco": 3333.33,
"imagemUrl": "https://loremflickr.com/640/480/product",
"estabelecimento": null,
"imagens": [],
"categorias": []
},
{
"id": 42,
"nome": "Produto 042",
"descricao": "Produto 042",
"preco": 3333.33,
"imagemUrl": "https://loremflickr.com/640/480/product",
"estabelecimento": null,
"imagens": [],
"categorias": []
},
{
"id": 1,
"nome": "Produto 001",
"descricao": "Produto 001",
"preco": 233.22,
"imagemUrl": "https://loremflickr.com/640/480/product",
"estabelecimento": null,
"imagens": [
{
"id": 1,
"url": "https://loremflickr.com/640/480/product"
},
{
"id": 2,
"url": "https://loremflickr.com/640/480/product"
}
],
"categorias": [
{
"id": 1,
"descricao": "Moda",
"icone": null
},
{
"id": 2,
"descricao": "Mercado",
"icone": null
}
]
},
{
"id": 21,
"nome": "Produto 021",
"descricao": "Produto 021",
"preco": 3333.33,
"imagemUrl": "https://loremflickr.com/640/480/product",
"estabelecimento": null,
"imagens": [],
"categorias": []
},
{
"id": 46,
"nome": "Produto 046",
"descricao": "Produto 046",
"preco": 3333.33,
"imagemUrl": "https://loremflickr.com/640/480/product",
"estabelecimento": null,
"imagens": [],
"categorias": []
},
{
"id": 48,
"nome": "Produto 048",
"descricao": "Produto 048",
"preco": 3333.33,
"imagemUrl": "https://loremflickr.com/640/480/product",
"estabelecimento": null,
"imagens": [],
"categorias": []
},
{
"id": 29,
"nome": "Produto 029",
"descricao": "Produto 029",
"preco": 3333.33,
"imagemUrl": "https://loremflickr.com/640/480/product",
"estabelecimento": null,
"imagens": [],
"categorias": []
},
{
"id": 14,
"nome": "Produto 014",
"descricao": "Produto 014",
"preco": 3333.33,
"imagemUrl": "https://loremflickr.com/640/480/product",
"estabelecimento": null,
"imagens": [],
"categorias": []
},
{
"id": 34,
"nome": "Produto 034",
"descricao": "Produto 034",
"preco": 3333.33,
"imagemUrl": "https://loremflickr.com/640/480/product",
"estabelecimento": null,
"imagens": [],
"categorias": []
},
{
"id": 6,
"nome": "Produto 006",
"descricao": "Produto 006",
"preco": 555.55,
"imagemUrl": "https://loremflickr.com/640/480/product",
"estabelecimento": null,
"imagens": [
{
"id": 11,
"url": "https://loremflickr.com/640/480/product"
},
{
"id": 12,
"url": "https://loremflickr.com/640/480/product"
}
],
"categorias": [
{
"id": 6,
"descricao": "Construção",
"icone": null
}
]
},
{
"id": 18,
"nome": "Produto 018",
"descricao": "Produto 018",
"preco": 3333.33,
"imagemUrl": "https://loremflickr.com/640/480/product",
"estabelecimento": null,
"imagens": [],
"categorias": []
},
{
"id": 28,
"nome": "Produto 028",
"descricao": "Produto 028",
"preco": 3333.33,
"imagemUrl": "https://loremflickr.com/640/480/product",
"estabelecimento": null,
"imagens": [],
"categorias": []
},
{
"id": 35,
"nome": "Produto 035",
"descricao": "Produto 035",
"preco": 3333.33,
"imagemUrl": "https://loremflickr.com/640/480/product",
"estabelecimento": null,
"imagens": [],
"categorias": []
},
{
"id": 16,
"nome": "Produto 016",
"descricao": "Produto 016",
"preco": 3333.33,
"imagemUrl": "https://loremflickr.com/640/480/product",
"estabelecimento": null,
"imagens": [],
"categorias": []
},
{
"id": 4,
"nome": "Produto 004",
"descricao": "Produto 004",
"preco": 333.33,
"imagemUrl": "https://loremflickr.com/640/480/product",
"estabelecimento": null,
"imagens": [
{
"id": 7,
"url": "https://loremflickr.com/640/480/product"
},
{
"id": 8,
"url": "https://loremflickr.com/640/480/product"
}
],
"categorias": [
{
"id": 4,
"descricao": "Celulares",
"icone": null
}
]
},
{
"id": 39,
"nome": "Produto 039",
"descricao": "Produto 039",
"preco": 3333.33,
"imagemUrl": "https://loremflickr.com/640/480/product",
"estabelecimento": null,
"imagens": [],
"categorias": []
},
{
"id": 41,
"nome": "Produto 041",
"descricao": "Produto 041",
"preco": 3333.33,
"imagemUrl": "https://loremflickr.com/640/480/product",
"estabelecimento": null,
"imagens": [],
"categorias": []
},
{
"id": 40,
"nome": "Produto 040",
"descricao": "Produto 040",
"preco": 3333.33,
"imagemUrl": "https://loremflickr.com/640/480/product",
"estabelecimento": null,
"imagens": [],
"categorias": []
},
{
"id": 23,
"nome": "Produto 023",
"descricao": "Produto 023",
"preco": 3333.33,
"imagemUrl": "https://loremflickr.com/640/480/product",
"estabelecimento": null,
"imagens": [],
"categorias": []
},
{
"id": 12,
"nome": "Produto 012",
"descricao": "Produto 012",
"preco": 2222.22,
"imagemUrl": "https://loremflickr.com/640/480/product",
"estabelecimento": null,
"imagens": [
{
"id": 22,
"url": "https://loremflickr.com/640/480/product"
},
{
"id": 23,
"url": "https://loremflickr.com/640/480/product"
}
],
"categorias": [
{
"id": 2,
"descricao": "Mercado",
"icone": null
}
]
},
{
"id": 17,
"nome": "Produto 017",
"descricao": "Produto 017",
"preco": 3333.33,
"imagemUrl": "https://loremflickr.com/640/480/product",
"estabelecimento": null,
"imagens": [],
"categorias": []
},
{
"id": 10,
"nome": "Produto 010",
"descricao": "Produto 010",
"preco": 999.99,
"imagemUrl": "https://loremflickr.com/640/480/product",
"estabelecimento": null,
"imagens": [
{
"id": 19,
"url": "https://loremflickr.com/640/480/product"
}
],
"categorias": [
{
"id": 10,
"descricao": "Saúde",
"icone": null
}
]
},
{
"id": 13,
"nome": "Produto 013",
"descricao": "Produto 013",
"preco": 3333.33,
"imagemUrl": "https://loremflickr.com/640/480/product",
"estabelecimento": null,
"imagens": [
{
"id": 24,
"url": "https://loremflickr.com/640/480/product"
}
],
"categorias": [
{
"id": 3,
"descricao": "Lar",
"icone": null
}
]
},
{
"id": 27,
"nome": "Produto 027",
"descricao": "Produto 027",
"preco": 3333.33,
"imagemUrl": "https://loremflickr.com/640/480/product",
"estabelecimento": null,
"imagens": [],
"categorias": []
},
{
"id": 30,
"nome": "Produto 030",
"descricao": "Produto 030",
"preco": 3333.33,
"imagemUrl": "https://loremflickr.com/640/480/product",
"estabelecimento": null,
"imagens": [],
"categorias": []
},
{
"id": 22,
"nome": "Produto 022",
"descricao": "Produto 022",
"preco": 3333.33,
"imagemUrl": "https://loremflickr.com/640/480/product",
"estabelecimento": null,
"imagens": [],
"categorias": []
},
{
"id": 31,
"nome": "Produto 031",
"descricao": "Produto 031",
"preco": 3333.33,
"imagemUrl": "https://loremflickr.com/640/480/product",
"estabelecimento": null,
"imagens": [],
"categorias": []
},
{
"id": 25,
"nome": "Produto 025",
"descricao": "Produto 025",
"preco": 3333.33,
"imagemUrl": "https://loremflickr.com/640/480/product",
"estabelecimento": null,
"imagens": [],
"categorias": []
},
{
"id": 45,
"nome": "Produto 045",
"descricao": "Produto 045",
"preco": 3333.33,
"imagemUrl": "https://loremflickr.com/640/480/product",
"estabelecimento": null,
"imagens": [],
"categorias": []
},
{
"id": 19,
"nome": "Produto 019",
"descricao": "Produto 019",
"preco": 3333.33,
"imagemUrl": "https://loremflickr.com/640/480/product",
"estabelecimento": null,
"imagens": [],
"categorias": []
},
{
"id": 47,
"nome": "Produto 047",
"descricao": "Produto 047",
"preco": 3333.33,
"imagemUrl": "https://loremflickr.com/640/480/product",
"estabelecimento": null,
"imagens": [],
"categorias": []
},
{
"id": 51,
"nome": "Nome",
"descricao": "Produto 001",
"preco": 233.22,
"imagemUrl": "https://loremflickr.com/640/480/product",
"estabelecimento": null,
"imagens": [],
"categorias": []
},
{
"id": 37,
"nome": "Produto 037",
"descricao": "Produto 037",
"preco": 3333.33,
"imagemUrl": "https://loremflickr.com/640/480/product",
"estabelecimento": null,
"imagens": [],
"categorias": []
},
{
"id": 20,
"nome": "Produto 020",
"descricao": "Produto 020",
"preco": 3333.33,
"imagemUrl": "https://loremflickr.com/640/480/product",
"estabelecimento": null,
"imagens": [],
"categorias": []
},
{
"id": 26,
"nome": "Produto 026",
"descricao": "Produto 026",
"preco": 3333.33,
"imagemUrl": "https://loremflickr.com/640/480/product",
"estabelecimento": null,
"imagens": [],
"categorias": []
},
{
"id": 44,
"nome": "Produto 044",
"descricao": "Produto 044",
"preco": 3333.33,
"imagemUrl": "https://loremflickr.com/640/480/product",
"estabelecimento": null,
"imagens": [],
"categorias": []
}
]
}
],
"pageable": {
"sort": {
"empty": true,
"unsorted": true,
"sorted": false
},
"offset": 0,
"pageNumber": 0,
"pageSize": 1,
"paged": true,
"unpaged": false
},
"last": false,
"totalPages": 25,
"totalElements": 25,
"first": true,
"size": 1,
"number": 0,
"sort": {
"empty": true,
"unsorted": true,
"sorted": false
},
"numberOfElements": 1,
"empty": false
} To get this result, I need to run the query as follows... Hibernate:
select
e1_0.id,
e1_0.cnpj,
e1_0.gestor_id,
e1_0.logo_url,
e1_0.nome,
e1_0.nome_completo,
e1_0.razao_social
from
estabelecimento e1_0 offset ? rows fetch first ? rows only
Hibernate:
select
p1_0.estabelecimento_id,
p1_0.id,
p1_0.descricao,
p1_0.imagem_url,
p1_0.nome,
p1_0.preco
from
produto p1_0
where
p1_0.estabelecimento_id in(select
e1_0.id
from
estabelecimento e1_0)
Hibernate:
select
count(e1_0.id)
from
estabelecimento e1_0 For the example above, I set the FETCH TYPE to EAGER, so that
@OneToMany(mappedBy = "estabelecimento", fetch = FetchType.EAGER)
@Fetch(FetchMode.SELECT)
private Set<Produto> produtos; With the request below. The summary is, is there any way, or am I doing something wrong so that the query assembly does not have separate SQL's? As in the last example, when using LAZY and Below I will leave a little about the sources
@Entity
@Table(name = "estabelecimento")
public class Estabelecimento implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
...
...
@OneToMany(mappedBy = "estabelecimento", fetch = FetchType.LAZY)
@Fetch(FetchMode.SELECT)
private Set<Produto> produtos;
}
@Entity
@Table(name = "estabelecimento")
public class Estabelecimento implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
...
...
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "estabelecimento_id")
private Estabelecimento estabelecimento;
}
@RestController
@RequestMapping("/api/estabelecimento/v1")
public class EstabelecimentoController {
private final IAuthenticationFacade authenticationFacade;
private final EstabelecimentoService estabelecimentoService;
private final EstabelecimentoEnderecoService estabelecimentoEnderecoService;
public EstabelecimentoController(
AuthenticationFacade authenticationFacade,
EstabelecimentoService estabelecimentoService,
EstabelecimentoEnderecoService estabelecimentoEnderecoService
) {
this.authenticationFacade = authenticationFacade;
this.estabelecimentoService = estabelecimentoService;
this.estabelecimentoEnderecoService = estabelecimentoEnderecoService;
}
@GetMapping
public ResponseEntity<Page<EstabelecimentoVO>> findAll(
@QuerydslPredicate(root = Estabelecimento.class) Predicate predicate,
@PageableDefault Pageable pageable,
@RequestParam(defaultValue = "", required = false) List<String> expand
) {
return ResponseEntity.ok(estabelecimentoService.findAll(
predicate,
pageable,
expand
));
}
}
@Service
public class EstabelecimentoService {
public final EstabelecimentoMapper estabelecimentoMapper;
public final EstabelecimentoRepository estabelecimentoRepository;
public EstabelecimentoService(
EstabelecimentoMapper estabelecimentoMapper,
EstabelecimentoRepository estabelecimentoRepository
) {
this.estabelecimentoMapper = estabelecimentoMapper;
this.estabelecimentoRepository = estabelecimentoRepository;
}
@Transactional(readOnly = true)
public Page<EstabelecimentoVO> findAll(
Predicate predicate,
Pageable pageable,
List<String> expand
) {
return estabelecimentoRepository.findAll(
predicate,
pageable,
new DynamicEntityGraph(EntityGraphType.LOAD, expand)
).map(estabelecimentoMapper::toDTO);
}
}
@Repository
public interface EstabelecimentoRepository extends
EntityGraphJpaRepository<Estabelecimento, Long>,
EntityGraphQuerydslPredicateExecutor<Estabelecimento>,
QuerydslBinderCustomizer<QEstabelecimento> {
@Override
default public void customize(QuerydslBindings bindings, QEstabelecimento root) {
System.out.println(".....customize......");
bindings.bind(String.class).first(
(StringPath path, String value) -> path.containsIgnoreCase(value));
System.out.println(".....customize......");
}
} |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 2 replies
-
Try to perform those queries with these entitygraphs using EntityManager directly and you will see this behaviour is controlled by the JPA implementation (e.g. Hibernate). |
Beta Was this translation helpful? Give feedback.
Try to perform those queries with these entitygraphs using EntityManager directly and you will see this behaviour is controlled by the JPA implementation (e.g. Hibernate).
Nothing to do in the current project.