I have three entities, seller (Vendedor), store (Loja) AND franchise (Franquia), the relashionship is described as below:
1 - Seller to store:Many to Many
2 - Store to franchise: Many to One
below is my JPQL query:
@Query("SELECT v FROM Vendedor v " +
"LEFT JOIN v.lojas l ON l.franquia.voToken = :tokenFranquia WHERE v.voId = :voId ")
Optional<Vendedor> getByVoIdAndTokenFranquia(Integer voId,String tokenFranquia);
In this query I'd like to get the Vendedor where its ERP id (voId) and tokenFranquia are some fixed value, the query above is expected to be translated as something like below:
SELECT *
FROM vendedores v
LEFT JOIN vendedores_lojas vl ON vl.vendedor_system_id = v.system_id
JOIN lojas l ON l.system_id = vl.loja_system_id
JOIN franquias f ON f.system_id = l.franquia_system_id
WHERE f.vo_token=:param1
AND v.vo_id = :param2
But it's translated to another completly different and illegible thing:
SELECT (ignoring selected columns because names are too many)
FROM vendedores v1_0
LEFT JOIN
(vendedores_lojas l1_0
JOIN (lojas l1_1
JOIN franquias f1_0
ON f1_0.system_id=l1_1.franquia_system_id)
ON l1_1.system_id=l1_0.loja_system_id)
ON v1_0.system_id=l1_0.vendedor_system_id AND f1_0.vo_token=?
WHERE v1_0.vo_id=?
Which get me wrong results.
The question is:
How can I get the desired result using JPQL?
@Entity
@Table(name="vendedores")
@Data
@EqualsAndHashCode(of="systemId")
public class Vendedor {
@Id
@GeneratedValue(strategy = GenerationType.UUID)
@Column(name="system_id")
private String systemId;
private Integer voId;
private String documento;
private String nome;
private Boolean isDigital;
private Boolean ativo;
@ManyToMany
@JoinTable(
name="vendedores_lojas",
joinColumns = @JoinColumn(name="vendedor_system_id",referencedColumnName = "system_id"),
inverseJoinColumns = @JoinColumn(name="loja_system_id",referencedColumnName = "system_id")
)
@JsonBackReference
private Set<Loja> lojas;
}
@Entity
@Table(name="lojas")
@Data
@EqualsAndHashCode(of="systemId")
public class Loja {
@Id
@GeneratedValue(strategy = GenerationType.UUID)
@Column(name="system_id")
private String systemId;
private Integer voId;//not unique
private String nome;
@ManyToOne
@JoinColumn(name="franquia_system_id")
@JsonBackReference
private Franquia franquia;
}
@Entity
@Table(name="franquias")
@Data
@EqualsAndHashCode(of="systemId")
public class Franquia {
@Id
@GeneratedValue(strategy = GenerationType.UUID)
private String systemId;
private String voToken;
private String cnpj;
private String nome;
private Boolean isMatriz;
}
I'm honestly thinking about giving up on JPQL queries and just using native ones, because the result is always a surprise
the problem may come from the join, I have the impression that it's not done correctly. The select seems to combine the join and the ‘where’ condition, which is not a good thing. As jpql doesn't have a separate ‘where’, neither does the generated sql.
Can you try this :
@Query("""
SELECT v FROM Vendedor v
LEFT JOIN FETCH v.lojas vl
LEFT JOIN FETCH vl.franquia f
WHERE v.voId = :voId AND f.voToken = :tokenFranquia
""")
Optional<Vendedor> getByVoIdAndTokenFranquia(Integer voId,String tokenFranquia);