Select rows using mapping table with JPA - sql

I do not know how to implement the query below in jpa, so please help.
select t.*
from team t
join team_memeber tm
on t.team_id = tm.team_id and tm.member_id = ?
The related entities are as follows.
public class Team {
#Id
int teamId;
#OneToMany(fetch = FetchType.LAZY)
#JoinColumn(name = "teamId")
Set<TeamMember> members = new HashSet<>();
}
public class TeamMember {
#Id
int id;
int teamId;
int memberId;
}

Related

Spring JPA Query. Join Table with #OneToMany properties

I have the following two Models:
class Game {
private long id;
#OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private Set<Team> teams;
...
}
class Team {
private long id;
#ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private Set<User> members;
...
}
The user model holds a String username.
Now I want to create a query that results in the Team when I pass the Game and username as parameters:
public interface TeamRepository extends Repository<Team, Long> {
#Query("select t from Game g join Team t where g = :game and :username member of t.members")
Team findTeamByUserInGame(Game game, String username);
}
But I can't figure out how to join the Game table with the Team table and then how to check if username is in members. Any help?
In case of join, you can query for g.teams.members.username=:username
public interface TeamRepository extends Repository<Team, Long> {
#Query("select g from Game g where g = :game and g.teams.members.username=:username")
Team findTeamByUserInGame(Game game, String username);
}
The following works:
#Query(value = "SELECT t FROM Game g join g.teams t where g = :game and exists (select m from g.teams join t.members m where m = :user)")

Nested query in JPQL

I have 2 entities -
#Table(name = "MM_MONITORING_CARD")
#Entity(name = "mm_MonitoringCard")
public class MonitoringCard extends StandardEntity {
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "CLIENT_ID")
private Counterparty client;
#Column(name = "START_DATE")
private LocalDate startDate;
#Column(name = "END_DATE")
private LocalDate endDate;
...otherColumn
}
and
#DiscriminatorColumn(name = "TYPE", discriminatorType = DiscriminatorType.STRING)
#Table(name = "MM_COUNTERPARTY")
#Entity(name = "mm_Counterparty")
#DiscriminatorValue("COUNTERPARTY")
#NamePattern("%s|name")
public class Counterparty extends StandardEntity {
#Column(name = "TYPE", insertable=false, updateable=false)
private String type;
...otherColumn
I need get all examples monitoringCard with condition - 1) between start date and end date 2) with Counterparty type = 'someType'
I do method -
List<MonitoringCard> monitoringCardList = dataManager.load(MonitoringCard.class)
.query("select distinct cm from mm_MonitoringCard m join mm_Counterparty cm where (m.current_date between cm.startDate and cm.endDate) and cm.type = :type")
.parameter("type", "someType")
.list();
but i get error, how can i make a correct request?
thanks
Your query is not correct. It should use a join like this:
select distinct m.Counterparty from mm_MonitoringCard m
where (m.current_date between m.Counterparty.startDate and m.Counterparty.endDate)
and m.Counterparty.type = :type
In JPA you don't need to do an explicit join when navigating on a ToOne relationship.

EclipseLink- JPQL join tables through query

I have problem with my JPQl. this is a one to many relationship with TrainRoute and TrainRouteStation. I'm trying to create a inner join and fetch the data. native SQL query working when I used mysql workbeanch and I'm trying convert it to JPQL. also, I was trying to fix from 2 days.
Error : Object comparisons can only be used with OneToOneMappings. Other mapping comparisons must be done through query keys or direct attribute level comparisons.
Class: TrainRoute
#Basic(optional = false)
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Id
#Column(name = "train_route_id", unique = true, nullable = false)
public Long getTrainRouteId() {
return this.trainRouteId;
}
public void setTrainRouteId(Long trainRouteId) {
this.trainRouteId = trainRouteId;
}
#OneToMany(cascade = CascadeType.ALL,fetch = FetchType.EAGER, mappedBy = "trainRoute")
public List<TrainRouteStationData> getTrainRouteStations() {
return this.trainRouteStations;
}
public void setTrainRouteStations(List<TrainRouteStationData> trainRouteStations) {
this.trainRouteStations = trainRouteStations;
}
Class: TrainRouteStation
#Basic(optional = false)
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Id
#Column(name = "train_route_station_id", unique = true, nullable = false)
public Long getTrainRouteStationId() {
return this.trainRouteStationId;
}
public void setTrainRouteStationId(Long trainRouteStationId) {
this.trainRouteStationId = trainRouteStationId;
}
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "train_route_id", nullable = false)
public TrainRouteData getTrainRoute() {
return this.trainRoute;
}
JPQL :"SELECT s FROM TrainRouteData t inner join TrainRouteStationData s ON t.trainRouteId=s.trainRoute where s.stationSeqN >=1 AND s.stationSeqN <=3 AND t.trainRouteDescX='Test1-Test2' order by s.stationSeqN asc"
Native SQL : SELECT train_route_station.* FROM train_route inner join train_route_station ON train_route.train_route_id=train_route_station.train_route_id where train_route_station.station_seq_n >= 1 AND train_route_station.station_seq_n <= 3 AND train_route.train_route_desc_x='Test1-Test2' order by train_route_station.station_seq_n asc
And it throw an error:
Exception Description: Object comparisons can only be used with OneToOneMappings. Other mapping comparisons must be done through query keys or direct attribute level comparisons.
Mapping: [org.eclipse.persistence.mappings.DirectToFieldMapping[trainRouteId-->train_route.train_route_id]]
Expression: [
Query Key trainRouteId
How can I change that query?
That's not how joins work in JPQL.
The correct query is
select s from TrainRouteData t inner join t.trainRouteStations s
where s.stationSeqN >= 1
and s.stationSeqN <= 3
and t.trainRouteDescX = 'Test1-Test2'
order by s.stationSeqN asc

How to convert my native SQL query into a JPQL query

I'm trying to convert a native SQL query into a JPQL query. Presented first are the JPA entities and the repository interface:
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<>();
}
I'm looking to get all LearnerPortfolioPerformanceCriteriaAchievements which have the same PerformanceCriteria as a given LearnerJobOnSiteChecklistSectionItem's Activity.
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
Understanding that I can replace my SQL ON with WHERE clauses, my best JPQL attempt so far is this:
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
However, running this JPQL throws the following exception:
Caused by: java.lang.IllegalStateException: No data type for node: org.hibernate.hql.internal.ast.tree.IdentNode
\-[IDENT] IdentNode: 'lppca' {originalText=lppca}
The following query will work:
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
Have created a sample application to test the query (I have used shorter and simpler class names to make it easy to read).

JPA Order by with two columns

I have two objects
Objects: Objeto, Comunicado and ComunicadoTramite
#Entity
#Table(name = "objetos")
#Inheritance(strategy = InheritanceType.JOINED)
public class Objeto extends Fact {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id_objeto", unique = true, nullable = false)
private Integer id;
#NotNull
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "dt_criacao")
private Date dataCriacao;
}
#Entity
#Table(name = "comunicados")
#PrimaryKeyJoinColumn(name = "cd_comunicado")
public class Comunicado extends Objeto {
#OneToMany(mappedBy = "comunicado")
private List<ComunicadoTramite> tramites;
}
#Entity
#Table(name = "comunicados_tramites")
#PrimaryKeyJoinColumn(name = "cd_tramite")
public class ComunicadoTramite extends Objeto {
#NotNull
#ManyToOne
#JoinColumn(name = "cd_comunicado")
private Comunicado comunicado;
The problem is, i want a list of Comunicado that is ordered by dataCriacao, the two objects (Comunicado and ComunicadoTramite) extends Objeto that contains dataCriacao.
if Comunicado.tramites.size() > 0 then get dataCriacao from the last ComunicadoTramite inserted
if Comunicado.tramites.size() = 0 then get dataCriacao from Comunicado.
SQL I did this
SELECT c.cd_comunicado, tb_tram.dt_criacao FROM comunicados AS c
INNER JOIN (
SELECT ct.cd_comunicado, MAX(obj.dt_criacao) AS dt_criacao FROM comunicados_tramites AS ct, objetos obj
WHERE ct.cd_tramite = obj.id_objeto GROUP BY ct.cd_comunicado
) AS tb_tram
ON c.cd_comunicado = tb_tram.cd_comunicado
)
UNION
(SELECT c.cd_comunicado, obj.dt_criacao FROM comunicados c, objetos obj
WHERE c.cd_comunicado = obj.id_objeto
AND c.cd_comunicado NOT IN (SELECT tram.cd_comunicado FROM comunicados_tramites tram))
ORDER BY dt_criacao DESC
I dont know how to do it in JPA... can anyone help me?
Based on Jorge' ideas i did this
SELECT obj FROM Objeto obj
WHERE obj.id IN (select comunicado.id from Comunicado comunicado
where comunicado NOT IN (SELECT tramite.comunicado from ComunicadoTramite tramite))
OR obj.id IN(select tramite.id from ComunicadoTramite tramite
where tramite.dataCriacao = (select MAX(tram.dataCriacao) from ComunicadoTramite tram WHERE tram.comunicado.id = tramite.comunicado.id)
group by tramite.comunicado)
ORDER BY obj.dataCriacao DESC