How to make a join with ON in jpa? ( Spring Data Jpa 1.4 ) - spring-data-jpa

I have this query, which I have tried in SQL and it goes perfectly
#Query("SELECT new es.abacor.elser.commons.empleado.EmpleadoList("+
"empleado.id,persona.nombre,persona.apellido1,persona.apellido2,persona.dni,persona.email)" +
" FROM rrhh.empleado as empleado" +
" INNER JOIN commons.persona AS persona ON empleado.persona_comun = persona.id" +
" WHERE" +
" empleado.persona_comun is not null" +
" and empleado.borrador = false" +
" and empleado.deleted is null" +
" and empleado.fecha_fin_contrato is null" +
" order by persona.nombre,persona.apellido1,persona.apellido2 asc")
public List<EmpleadoList> allEmpleadosList();
But I get the following error when executing within my project
Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: ON near line 1, column 217 [SELECT new es.abacor.elser.commons.empleado.EmpleadoList(empleado.id,persona.nombre,persona.apellido1,persona.apellido2,persona.dni,persona.email) FROM rrhh.empleado as empleado INNER JOIN commons.persona AS persona ON empleado.persona_comun = persona.id WHERE empleado.persona_comun is not null and empleado.borrador = false and empleado.deleted is null and empleado.fecha_fin_contrato is null order by persona.nombre,persona.apellido1,persona.apellido2 asc]
Someone knows what I'm doing wrong, I do not know what to do anymore.

JPA doesn't work on tables, it works on objects. If you want to use native queries you have to add nativeQuery=true to the Definition:
#Query(nativeQuery=true, <SQL-Statement>)
otherwise the ON clasue will be generated from the annotations in your entities

Related

Syntax error when querying results directly to a DTO

My native query -
interface PodcastRepository: JpaRepository<Podcast, Long> {
#Query(value = "SELECT new com.krtkush.sample.modules.podcast.models.PodcastDTO" +
"(p.id, p.author, p.title, p.description c.name, c2.name) " +
"AS sub_category_name FROM podcasts p " +
"LEFT JOIN categories c ON p.podcast_category_id = c.category_id " +
"LEFT JOIN categories c2 ON p.podcast_subcategory_id = c2.category_id " +
"WHERE p.podcast_owner = :ownerId", nativeQuery = true)
fun getPodcastsByOwner(#Param("ownerId")owner: Long): List<PodcastDTO>
}
However, when I execute the function I get the following error -
org.postgresql.util.PSQLException: ERROR: syntax error at or near "." Position: 15
position 15 is . after SELECT new com
I'm following this tutorial - https://smarterco.de/spring-data-jpa-query-result-to-dto/
The difference is that I'm using SQL rather than JPQL.

Transforming complex postgres query into JPQL for Spring Hibernate repository

I have the following Postgres SQL query, in order to get alerts with the latest date:
SELECT latest_alerts.subject_id,
latest_alerts.alertconfiguration_id_id,
latest_alerts.alert_level,
latest_alerts.maxdate
FROM (SELECT subject_id,
alertconfiguration_id_id,
alert_level,
Max(date) AS maxdate
FROM alert
WHERE subject_id IN ( 'da157532-8de5-4c0c-8608-d924e670d5db', '63b99886-77c8-4784-b8f0-7ff5310f1272' )
AND alertconfiguration_id_id IN (
'6feb6b8b-6b96-4d5d-ac58-713b3cd637a0'
)
GROUP BY subject_id,
alertconfiguration_id_id,
alert_level) AS latest_alerts
INNER JOIN alert
ON alert.date = latest_alerts.maxdate
AND alert.subject_id = latest_alerts.subject_id
AND alert.alertconfiguration_id_id =
latest_alerts.alertconfiguration_id_id
AND alert.alert_level IN ( 'WARNING' )
ORDER BY latest_alerts.maxdate DESC;
This runs well on the postgres database generated by Hibernate. Note the odd id_id construction is because of an embedded key.
But I'm struggling to transform this into a JPA/JPQL query that I can use in a Spring Boot application. So far I have this:
#Query("SELECT" +
" latest_alerts.subject," +
" latest_alerts.alertConfiguration," +
" latest_alerts.alertLevel," +
" latest_alerts.max_date" +
"FROM" +
" (SELECT" +
" subject," +
" alertConfiguration," +
" alertLevel," +
" MAX(date) AS max_date" +
" FROM" +
" alert" +
" WHERE" +
" subject.id IN (:subjectIds) AND alertConfiguration.id.id IN (:alertConfigurationIds)" +
" GROUP BY" +
" subject, alertConfiguration, alertLevel) AS latest_alerts" +
" INNER JOIN" +
" alert" +
" ON" +
" alert.date = latest_alerts.max_date" +
" AND alert.subject = latest_alerts.subject" +
" AND alert.alertConfiguration = latest_alerts.alertConfiguration" +
" AND alert.alertlevel IN (:alertLevels)" +
" ORDER BY latest_alerts.date DESC")
Page<Alert> findLatest(#Param("subjectIds") List<UUID> subjectIds,
#Param("alertConfigurationIds") List<UUID> alertConfigurationIds,
#Param("alertLevels") List<AlertLevel> alertLevels,
Pageable pageable);
But Hibernate doesn't understand what to do with this to the point where it actually throws a nullpointer while parsing this query.
Caused by: java.lang.IllegalArgumentException: Validation failed for query for method public abstract org.springframework.data.domain.Page ournamespace.sense.repository.AlertRepository.findLatest(java.util.List,java.util.List,java.util.List,org.springframework.data.domain.Pageable)!
at org.springframework.data.jpa.repository.query.SimpleJpaQuery.validateQuery(SimpleJpaQuery.java:93)
at org.springframework.data.jpa.repository.query.SimpleJpaQuery.<init>(SimpleJpaQuery.java:63)
... many more
Caused by: java.lang.NullPointerException
at org.hibernate.hql.internal.antlr.HqlBaseParser.identPrimary(HqlBaseParser.java:4355)
at org.hibernate.hql.internal.antlr.HqlBaseParser.primaryExpression(HqlBaseParser.java:993)
at org.hibernate.hql.internal.antlr.HqlBaseParser.atom(HqlBaseParser.java:3549)
Any idea if this kind of query is even possible? With a nullpointer thrown by Hibernate it's a bit hard to see what part of the query is the problem.
Cannot do it with Hibernate. From the documentation:
Note that HQL subqueries can occur only in the select or where
clauses.
But you can use native query:
#Query(
value = "SELECT latest_alerts.subject_id,
latest_alerts.alertconfiguration_id_id,
latest_alerts.alert_level,
latest_alerts.maxdate ...
FROM ...",
nativeQuery = true)
Page<Alert> findLatest(#Param("subjectIds") List<UUID> subjectIds,
#Param("alertConfigurationIds") List<UUID> alertConfigurationIds,
#Param("alertLevels") List<AlertLevel> alertLevels,
Pageable pageable);

ADO.NET working with SQL and database

I'm getting an exception error saying missing operators can anyone help
string sql = "Select SalesPerson.Name, Item.Description, Orders.Quantity, Orders.OrderDate"
+ "From([Orders]"
+ "Inner Join[SalesPerson] On Orders.SalesPersonID=SalesPerson.SalesPersonID)"
+ "Inner Join[Item] On Orders.ItemNumber=Item.ItemNumber"
+ "Where Orders.CustomerID=#customer Order by Orders.OrderDate DESC";
You need to add some spaces at the end of each of your lines of SQL!
string sql = "SELECT SalesPerson.Name, Item.Description, Orders.Quantity, Orders.OrderDate "
+ "FROM [Orders] "
+ "INNER JOIN [SalesPerson] ON Orders.SalesPersonID = SalesPerson.SalesPersonID "
+ "INNER JOIN [Item] ON Orders.ItemNumber = Item.ItemNumber "
+ "WHERE Orders.CustomerID = #customer "
+ "ORDER BY Orders.OrderDate DESC";
Otherwise, your SQL ends up being
Select ..... Orders.OrderDateFROM([Orders]Inner Join[SalesPerson] .....
and so on - and that's just not valid SQL.
I also removed some unnecessary parenthesis around the JOIN operators - those are only needed for MS Access, but since you're saying you're using ADO.NET, I assume this is not for MS Access and therefore, those parenthesis are not needed

Incomplete data while fetching through Named Query JPA2.0

I have an entity named ReqestDetail and done association and mapping as below snippet:
#ManyToOne
#JoinColumn(name="STATUS_C")
private StatusCode statusCode;
//bi-directional many-to-one association to RequestAddressDetail
#OneToMany(mappedBy="requestDetail")
private List<RequestAddressDetail> addressDetails;
I have created below Named Query to fetch the details on the basis of address.
TypedQuery<RequestDetail> query = em.createQuery( "SELECT t FROM RequestDetail t" +
" LEFT JOIN t.employeeDetail e " +
" LEFT JOIN t.addressDetails ao " +
" LEFT JOIN t.addressDetails ad " +
" WHERE (e.employeeI IN ( :employeeIds ) ) AND " +
" (ao.postI = :postO AND ao.addressTypeC = :addressTypeO " +
" AND ad.postI = :PostD AND ad.addressTypeC = :addressTypeD )" ,
RequestDetail.class );
However, when I call query.getResultList(), it is only giving me data of RequestDetail Entity but not of the mapping joins I have mentioned in that entity.
Please advise...
why do you think it should give you some joined objects? Your candidate for the query is RequestDetail, so it gives that. If you did a JOIN FETCH then you can fetch other fields, but you haven't done that (so change those LEFT JOIN to LEFT JOIN FETCH) - a JOIN (without FETCH) is simply a convenience way of forming the query.. Alternatively you could set the entity graph to fetch, or set the fetch on the field itself if you wanted those fetching

How to execute raw query in JPA?

I'm trying to execute a raw query like this:
em.createNativeQuery(
"WITH RECURSIVE recursetree(id, parent_id) AS (\n" +
"SELECT id, parent_g_id FROM group WHERE parent_g_id = 2\n" +
"UNION\n" +
" SELECT t.id, t.parent_g_id\n" +
" FROM group t\n" +
" JOIN recursetree rt ON rt.id = t.parent_g_id\n" +
" )\n" +
"SELECT * FROM recursetree;").getResultList();
On the Postgres side (via PGAdmin) it works fine, but from Java it get the following error:
java.lang.IllegalArgumentException: argument type mismatch
What do I do wrong? How to execute a really raw query on Postgres from a Java EE environment?