2016-06-01 11 views
0

Ich versuche, eine native SQL-Abfrage in eine JPQL-Abfrage zu konvertieren. Vorgestellt werden zunächst die JPA Entitäten und das Repository-Schnittstelle:So konvertieren Sie meine native SQL-Abfrage in eine JPQL-Abfrage

LearnerActivity

@Entity 
@Table(name = "learner_activity") 
public class LearnerActivity implements Serializable { 
    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private Long id; 

    @ManyToMany 
    @JoinTable(name = "learner_activity_unit", 
       joinColumns = @JoinColumn(name="learner_activitys_id", referencedColumnName="ID"), 
       inverseJoinColumns = @JoinColumn(name="units_id", referencedColumnName="ID")) 
    private Set<Unit> units = new HashSet<>(); 

    @ManyToMany 
    @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) 
    @JoinTable(name = "learner_activity_performance_criteria", 
       joinColumns = @JoinColumn(name="learner_activitys_id", referencedColumnName="ID"), 
       inverseJoinColumns = @JoinColumn(name="performance_criterias_id", referencedColumnName="ID")) 
    private Set<PerformanceCriteria> performanceCriterias = new HashSet<>(); 
} 

LearnerJobOnSiteChecklistSectionItem

@Entity 
@Table(name = "learner_job_on_site_checklist_section_item") 
public class LearnerJobOnSiteChecklistSectionItem implements Serializable { 
    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private Long id; 

    @ManyToOne 
    @JoinColumn(name = "learner_activity_id") 
    private LearnerActivity learnerActivity; 
} 

LearnerPortfolioPerformanceCriteriaAchievement

@Entity 
@Table(name = "learner_portfolio_performance_criteria_achievement") 
public class LearnerPortfolioPerformanceCriteriaAchievement implements Serializable { 
    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private Long id; 

    @ManyToOne 
    @JoinColumn(name = "performance_criteria_id") 
    private PerformanceCriteria performanceCriteria; 

    @ManyToMany 
    @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) 
    @JoinTable(name = "learner_portfolio_performance_criteria_achievement_learner_job_on_site_checklist_section_item", 
       joinColumns = @JoinColumn(name="learner_portfolio_performance_criteria_achievements_id", referencedColumnName="ID"), 
       inverseJoinColumns = @JoinColumn(name="learner_job_on_site_checklist_section_items_id", referencedColumnName="ID")) 
    private Set<LearnerJobOnSiteChecklistSectionItem> learnerJobOnSiteChecklistSectionItems = new HashSet<>(); 
} 

Ich bin auf der Suche alle LearnerPortfolioPerformanceCriteriaAchievement s zu erhalten, die die gleiche PerformanceCriteria als gegeben LearnerJobOnSiteChecklistSectionItem ‚s Activity haben.

LearnerPortfolioPerformanceCriteriaAchievementRepository

public interface LearnerPortfolioPerformanceCriteriaAchievementRepository extends JpaRepository<LearnerPortfolioPerformanceCriteriaAchievement,Long> { 
    @Query("select distinct lppca from LearnerJobOnSiteChecklistSectionItem si inner join si.learnerActivity la inner join LearnerPortfolioPerformanceCriteriaAchievement lppca where lppca.performanceCriteria member of la.performanceCriterias and si.id =:sectionItemId") 
    public List<LearnerPortfolioPerformanceCriteriaAchievement> findForSectionItem(@Param("sectionItemId") Long sectionItemId); 
} 

Native SQL

SELECT 
    a.id 
FROM 
    learner_job_on_site_checklist_section_item AS i 
JOIN 
    learner_activity_performance_criteria AS c 
ON 
    c.learned_activitys_id = i.learned_activitys_id 
INNER JOIN 
    learner_portfolio_performance_criteria_achievement AS a 
ON 
    a.performance_criteria_id = c.performance_criterias_id 
where i.id = 2 

Verständnis, dass ich ersetzen meine SQL ON mit WHERE Klauseln, mein bester JPQL Versuch so weit dies:

SELECT 
    DISTINCT lppca 
FROM 
    LearnerJobOnSiteChecklistSectionItem si 
INNER JOIN 
    si.learnerActivity la 
INNER JOIN 
    LearnerPortfolioPerformanceCriteriaAchievement lppca 
WHERE 
    lppca.performanceCriteria MEMBER OF la.performanceCriterias 
AND si.id =:sectionItemId 

jedoch diese JPQL läuft wirft die folgende Ausnahme:

Caused by: java.lang.IllegalStateException: No data type for node: org.hibernate.hql.internal.ast.tree.IdentNode 
\-[IDENT] IdentNode: 'lppca' {originalText=lppca} 
+0

Wenn Sie eine Frage stellen, halten Sie den Code so klein wie möglich, damit die Leser sie leicht lesen können. Im Moment ist es aufgrund der Länge des Codes und der erschreckend langen Klassennamen zu umständlich. Ich habe etwas Code entfernt, der keinen Einfluss auf die Problembeschreibung oder die Antwort hat, so dass die Frage leichter zu lesen ist. – manish

+0

Schätzen Sie die Zeit, die Sie verbracht haben. Kommentare für zukünftige Fragen notiert. Vielen Dank. –

Antwort

0

Die folgende Abfrage funktioniert:

SELECT 
    a 
FROM 
    LearnerPortfolioPerformanceCriteriaAchievement a 
    , LearnerActivity        v 
    , LearnerJobOnSiteChecklistSectionItem   i 
WHERE 
    i.id           = :sectionItemId 
AND i.learnerActivity        = v 
AND a.performanceCriteria       MEMBER OF v.performanceCriterias 
AND i            MEMBER OF a.learnerJobOnSiteChecklistSectionItems 

Haben eine sample application erstellt, um die Abfrage zu testen (ich habe kürzere und einfachere Klassennamen verwendet, um es einfach zu lesen).