QuerySyntaxException - unexpected token: a (SQL statement not correct?) - java

I get following error message when trying to fire an SQl Statement....the exception:
QuerySyntaxException: unexpected token: a near line 1, column 127 [SELECT DISTINCT e FROM com.taqwaapps.entity.Event e, com.taqwaapps.entity.Appointment a WHERE e.eventId = a.event.eventIdĀ AND a.district.city.name = 'Jeddah' ]
It seems that following SQL Statement is not correct:
#Query("SELECT DISTINCT e "
+ "FROM Event e, Appointment a "
+ "WHERE e.eventId = a.event.eventIdĀ "
+ "AND a.district.city.name = 'Jeddah' ")
List<Event> getEventsFiltered();
My Objects are:
#Entity
public class Event {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Long eventId;
}
and
#Entity
public class Appointment {
#JsonIgnore
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "eventId")
private Event event;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "districtId")
private District district;
What is wrong?

I found the Problem:
In the past in school time I learned from my informatics Teacher that in SQL it can happen that there is an hidden character which we entered or which got entered but we dont see it. So just write the SQL again using plain writing

Related

How to use "IN" command properly with JPQL?

I'm having some problens on using the commando "IN" on my jpql, here's the case:
I have these classes:
public class Empresa{
#Id
#Column(nullable = false, unique = true)
#GeneratedValue
private Long id;
#JoinColumn(name = "id_tipo_empresa")
#OneToOne(cascade = CascadeType.DETACH)
private TipoEmpresa tipoEmpresa;
}
public class TipoEmpresa{
#Id
#Column(unique = true, nullable = false)
#GeneratedValue
private Long id;
private Long valor;
}
Then I have this service, that sends a List of "TipoEmpresa" to my EmpresaRepository's query:
SERVICE
public List<Empresa> getEmpresasByTipoEmpresaAndTipoStatus(List<TipoEmpresa>tiposEmpresa) {
List<Empresa> listaDeEmpresas=empresaRepository.getEmpresasByTipoEmpresa(tiposEmpresa);
return listaDeEmpresas;
}
REPOSITORY
#Query(name = "SELECT E FROM Empresa E WHERE E.tipoEmpresa IN(:tipoEmpresa)")
List<Empresa> getEmpresasByTipoEmpresaAndTipoStatus(#Param("tipoEmpresa") List<TipoEmpresa> tipoEmpresa);
As you can see I'm trying to get all "Empresa" that have a "tipoEmpresa" listed on my List, but when colling the service I get this error:
java.sql.SQLException: Operand should contain 1 column(s)
I don't know what to do anymore, tried everything I could think of, what am I doing wrong ?
hi Dude ! first things first, thanks for helping !
.
.
.
I tried g.Irani's suggestion, changed my code, that got like this:
Repository
#Query(name = "SELECT E FROM Empresa E WHERE E.tipoEmpresa.id IN :tipoEmpresa ")
List<Empresa> getEmpresasByTipoEmpresaAndTipoStatus(#Param("tipoEmpresa") List<Long> tipoEmpresa);
Service
//just a test...
List<Long> test =Arrays.asList(100l, 200l);
List<Empresa> listaDeEmpresas=empresaRepository.getEmpresasByTipoEmpresa(test);
But now I got this error message:
java.lang.IllegalArgumentException: Parameter value element [100] did not match expected type [br.com.entities.TipoEmpresa (n/a)]
Any thoughts about it ?
after IN in WHERE clause, you should present a list with 1 column.
tipoEmpresa in below query of your code is a class (with 2 columns)
#Query(name = "SELECT E FROM Empresa E WHERE E.tipoEmpresa IN(:tipoEmpresa)")
you can use
#Query(name = "SELECT E FROM Empresa E WHERE E.tipoEmpresa.id IN(:tipoEmpresaIDs)")
then prepare a list of tipoEmpresa IDs and set to :tipoEmpresaIDs
notice that, In JPA when using IN, you don't need ( ) after IN. (just use ... IN :tipoEmpresaIDs)

How to fetch object via spring data(jpql) that is in relation via next other object

I'm using spring data with JPQL grouping select, everything works and stats are counted, but when I want to acces to competition object I'm getting this error:
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
I have these entities that I want to collect for stats
#Entity
public class BetCourse {
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "MATCH_ID", nullable = false)
private BetMatch betMatch;
}
#Entity
public class BetMatch {
#OneToMany(fetch = FetchType.LAZY, mappedBy = "betMatch")
private List<BetCourse> courses = new ArrayList<>();
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "COMPETITION_ID", nullable = false)
private Competition competition;
}
#Entity
public class Competition {
#OneToMany(fetch = FetchType.LAZY, mappedBy = "competition")
private List<BetMatch> betMatches = new ArrayList<>();
#OneToMany(fetch = FetchType.LAZY, mappedBy = "competition")
private List<Stats> stats = new ArrayList<>();
}
And I'm digging data from these classes to the Stats class
#Entity
public class Stats {
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "COMPETITION_ID", nullable = false)
private Competition competition;
}
via this select:
#Query("select new Stats(" +
"c.course, " +
"c.courseType, " +
"count(*), " +
"SUM(CASE WHEN win = true THEN 1 ELSE 0 END), " +
"c.betMatch.competition) " +
"from BetCourse c " +
group by c.course, c.betMatch.competition, c.courseType")
public List<Stats> computeStatsByBetShop();
and when I acces to competiton object
stat.getCompetition()
How can I fetch this object? Is it possible to somehow combine with join fetch?
After creating some code spike, I came with a solution that is pretty easy and straight to follow. Instead of starting your JPQL from the BetCourse table, and do the joins from there, you should start from the Competition table, and then do the inner joins until BetCourse.
This is because from the point of view of BetCourse, the entity is a ManyToOne, and them the JPA somehow get lost. Just doing in the inverse order solve your issue.
#Query("select new Stats(" +
"c.course, " +
"c.courseType, " +
"count(c), " +
"SUM(CASE WHEN win = true THEN 1 ELSE 0 END), " +
"cpt) " +
"from Competition cpt " +
"inner join cpt.betMatches bm " +
"inner join bm.courses c " +
"group by c.course, c.courseType, cpt")
#ReadOnlyProperty
public List<Stats> computeStatsByBetShop();
And here goes a GitHub minimum code following your classes, so you can use it as example, in case it still does not work for you.
Cheers, Nikolas

Fetching entities in OneToOne Mapping returns wrong results

I have this entities
ResourceForSearch.java
#Entity
#Table(name = "RESOURCES")
public class ResourceForSearch {
#Id
#Column(name = "IDRESOURCE")
private long id;
private String defaultText;
#OneToOne
#JoinColumn(name = "IDRESOURCE", referencedColumnName = "IDRESOURCE")
private TranslationForSearch translation;
// getters and setters
}
TranslationForSearch.java
#Entity
#Table(name = "TRANSLATIONS")
public class TranslationForSearch {
#Column(name = "IDTRANSLATION")
private long id;
#Column(name = "IDLANGUAGE")
private long languageId;
private String translation;
#Id
private long idResource;
// getters and setters
}
Normally a RESOURCE is in relation with N TRANSLATION(s) and a TRANSLATION is identified by IDTRANSLATION, but given a value for TRANSLATIONS.IDLANGUAGE, this relation becomes OneToOne because in a certain language (identified by IDLANGUAGE) the translation is only one for each resource (a resource is a label I want to translate in different languages).
So only for search purposes I can put the #Id annotation on the TranslationForSearch.idResource field, not on the TranslationForSearch.id field.
Here is the Criteria query I wrote:
CriteriaQuery<ResourceForSearch> searchQuery = criteriaBuilder.createQuery(ResourceForSearch.class);
Root<ResourceForSearch> searchRoot = searchQuery.from(ResourceForSearch.class);
searchQuery.select(searchRoot);
Join<ResourceForSearch, TranslationForSearch> translationJoin = resourceRoot.join("translation", JoinType.LEFT);
// Here I filter the JOIN clause by language id, having the OneToOne relationship
translationJoin.on(criteriaBuilder.equal(translationJoin.get("languageId"), 22));
// Here I want to fetch the TRANSLATIONS included in the join
resourceRoot.fetch("translation");
List<ResourceForSearch> resultList = em.createQuery(searchQuery).getResultList();
The problem here is that the statement
for (ResourceForSearch resourceForSearch : resultList) {
if (resourceForSearch.getTranslation() != null)
System.out.println("Resource id: " + resourceForSearch.getId() + " Language id: " + resourceForSearch.getTranslation().getLanguageId());
}
Prints
Resource id: 81 Language id 22
Resource id: 85 Language id 30
Resource id: 86 Language id 30
Resource id: 87 Language id 30
Resource id: 88 Language id 30
It seems that the fetch in the query doesn't work because the query is returning entities which doesn't respect the join clause.
EDIT 1:
This is the SQL query generated by Hibernate
SELECT resourcefo0_.IDRESOURCE AS IDRESOURCE1_2_,
resourcefo0_.defaultText AS defaultText6_2_
FROM WIN_RESOURCES resourcefo0_
LEFT OUTER JOIN WIN_TRANSLATIONS translatio1_
ON resourcefo0_.IDRESOURCE =translatio1_.idResource
AND (translatio1_.IDLANGUAGE =22)
Which returns a number of rows equal to the numbero of rows of WIN_RESOURCES. Moreover if I edit the query adding the select field translatio1_.IDLANGUAGE, it returns me a value of 22 of null (not 30).
SELECT resourcefo0_.IDRESOURCE AS IDRESOURCE1_2_,
resourcefo0_.defaultText AS defaultText6_2_,
translatio1_.IDLANGUAGE
FROM WIN_RESOURCES resourcefo0_
LEFT OUTER JOIN WIN_TRANSLATIONS translatio1_
ON resourcefo0_.IDRESOURCE =translatio1_.idResource
AND (translatio1_.IDLANGUAGE =22)
Where can be the problem?
Thank you

Retrieving object children while using Transformers.aliasToBean

I've got a question regarding children retrieval when using Transformers.aliasToBean function in Hibernate. I've wrote a query which populates my object, but when I try to populate children query doesn't work. I'll post sample code first and add generated SQL and exception below.
Parent
public class Parent {
#Id
#Column(name="id")
#GeneratedValue
private long id;
#Column(name="name")
private String name;
#OneToMany(cascade = CascadeType.ALL)
#JoinColumn(name="parent_id")
#LazyCollection(LazyCollectionOption.FALSE)
private List<Child> children;
#Transient
private long someCount;
// public constructor + getters and setters
}
Child
public class Child {
#Id
#Column(name="id")
#GeneratedValue
private long id;
// public constructor + getters and setters
}
Query
Query query = session.createQuery("SELECT p.id as id, p.name as name, "
+ " (SELECT COUNT(*) FROM stat WHERE parent_id=p.id) as someCount, "
+ " FROM " + Parent.class.getSimpleName() + " p ")
.setResultTransformer(Transformers.aliasToBean(Parent.class));
Basically when I try to include p.children as children right in the first line of query I get the following sql generated by hibernate:
select parent0_.id as col_0_0_, parent0_.name as col_1_0_, . as col_2_0_,
(select count(*) from stats stat3_ where parent_id=parent0_.id) as col_3_0_, child2_.id
as id1_2_1_ from inner join child child2_ on parent0_.id=child2_.parent_id
And the error is:
WARN: SQL Error: 0, SQLState: 42601
ERROR: ERROR: syntax error at or near "." at position 60
That position 60 corresponds to , . as col_2_0_, the position before the dot in the first line of the query. Basically it seems to retrieve the children, but generated SQL prevents it from successfully executing the query.
Any help appreciated!
Simply speaking, you can not add p.children to result columns of SELECT, because it's a collection, and only entities or scalars are allowed here. But you can try this alternative:
Query query = session.createQuery("SELECT p, "
+ " (SELECT COUNT(*) FROM stat WHERE parent_id=p.id) "
+ " FROM " + Parent.class.getSimpleName() + " p " +
+ " LEFT JOIN FETCH p.children ");
for (Object[] row : (List<Object[]>)query.list()) {
Parent p = (Parent)row[0];
p.setSomeCount(((Number)row[1]).longValue());
}
Please tell if it really works for you.

JPA/Hibernate Join Query

The goal is to retrieve all users (not messages) that have sent a message to a particular user (the current logged-in user), or have received a message from this user (even if they didn't reply yet). I've tried many queries, but to no avail. (I have the id of the logged-in user).
Do you have any ideas? I'm assuming I need to do a join on Message & RegisteredUser classes, but not sure how it'll work since the Message has the 'sender' & 'receiver' which makes the query a bit more complex.
RegisteredUser class (doesn't have a reference to Message):
#Entity
#Table(name = "USER")
public class RegisteredUser implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
Message class:
#Entity
#Table(name = "MESSAGE")
public class Message implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
int id;
#ManyToOne
#JoinColumn(name = "receiverId")
RegisteredUser receiver;
#ManyToOne
#JoinColumn(name = "senderId")
RegisteredUser sender;
I'm using jpa 2.0 and hibernate 3.5.6.
Thanks!
//EDIT -- The Solution, thanks to Andrey
"select distinct u from RegisteredUser u where u in (select m1.sender from Message m1 join m1.receiver r where r.id = " + user.getId() + ") or u in (select m2.receiver from Message m2 join m2.sender s where s.id = " + user.getId() + ")"
select distinct u from RegisteredUser u where
u in (select m1.sender from Message m1 join m1.receiver r where r.id = " + user.getId() + ") or
u in (select m2.receiver from Message m2 join m2.sender s where s.id = " + user.getId() + ")"

Categories