Mysql
 sql >> Base de données >  >> RDS >> Mysql

problèmes avec OneToMany incluant une clause de filtre au printemps jpa

  • Signification de select d from TKBData d JOIN d.columns c WHERE c.name = column1 est

    1. Rechercher un objet TKBData auquel il a une column associée objet pour lequel name est column1
    2. Une fois qu'il a été décidé quel TKBData a au moins une column objet pour lequel name est column1 , puis il renverra toute sa column associée objets sur lesquels vous n'avez aucun contrôle dans JPA. (voir Ma réponse à une autre question ). L'alternative consiste à écrire du sql natif et à renvoyer des objets non-entité personnalisés
    3. Par exemple, vous avez TKBDATA_1 avec column1 et column2 associé, vous avez également TKBDATA_2 avec column3 associé.
    4. Lorsque vous exécuterez votre requête, elle ignorera TKBDATA_2 et décide de retourner TKBDATA_1 car il a au moins une column objet avec name =column2 . Mais après cela vous ne contrôlez pas la column associée objets à renvoyer pour TKBDATA_1 et JPA renverra tous les objets de colonne associés
    5. Si vous n'êtes pas sûr de la raison, lisez la session d'hibernation. Comment elle fournit une présentation unique de toute entrée associée en mémoire. C'est la base de sa dirty checking et repeatable read
  • Mettez à jour votre @OneToMany comme suit

   @OneToMany(fetch = FetchType.EAGER, 
           cascade = CascadeType.ALL, orphanRemoval = true)
   @Builder.Default
   @JoinTable(name = "TKBDATA_TKBCOLUMN", 
           joinColumns = @JoinColumn(name = "TKBDATA_ID"), 
           inverseJoinColumns = @JoinColumn(name = "COLUMNS_ID"))
   private Set<TKBColumn> columns = Sets.newHashSet();
  • En ce qui concerne le langage de requête JPA, j'aimerais penser en termes d'interrogation d'une collection d'objets en mémoire.

  • Essayez maintenant de décrire la signification des deux requêtes suivantes en termes d'objets.

   select d from TKBData d LEFT JOIN d.columns c WHERE c.name = :name
           vs
   select d from TKBData d JOIN d.columns c WHERE c.name = :name
  • N'oubliez pas, contrairement à SQL où vous sélectionnez toutes les colonnes ici, vous avez dit que vous souhaitez sélectionner des objets TKBData et restreindre les objets TKBData à renvoyer.

  • Donc, pour obtenir le même résultat qu'avec votre sql natif, utilisez la deuxième requête JPA

Remarque :

Même si vous avez utilisé une jointure gauche dans votre requête sql, il s'agit en fait d'une requête sql de jointure interne car vous avez également appliqué un where condition à la table la plus à droite sur cette jointure.