Spring Repositories and DATA_FORMAT with nativeQuery=false - java

I am trying do something super simple but with Spring Repositories somethings is a bit hard. Basically I wanted to group by with DATE_FORMAT, example:
#Query("SELECT " +
" new users.bridge.models.dto.PerformanceDTO(sum(t.gl), sum(t.gl)) " +
"FROM " +
" Transaction t " +
"GROUP BY DATA_FORMATE(t.createdDate,'%Y-%m-%d')")
But it throws a syntax error. Is there a way to do that with spring repositories? I don't want to use nativeQuery=true flag, otherwise I can not use this syntax
new gara.users.bridge.models.dto.PerformanceDTO(sum(t.gl), sum(t.gl))
UPDATE:
The erros are:
all the java stack is quite big but:
org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: asc near line 1, column 180 [SELECT new gara.users.bridge.models.dto.PerformanceDTO(sum(t.gl), sum(t.gl),t.createdDate) FROM gara.model.db.Transaction t GROUP BY DATE_FORMAT(t.createdDate,'%Y-%m-%d') asc]

If you specify nativeQuery=false (the default) you need to use valid JPQL.
JPQL doesn't know the function DATE_FORMAT but you can use the generic FUNCTION function which allows you to call arbitrary SQL functions.
So a group by clause like this should work: GROUP BY FUNCTION('DATA_FORMAT', t.createdDate,'%Y-%m-%d')
Just be aware that such queries aren't portable between databases.
but with Spring Repositories somethings is a bit hard.
You can always fall back on custom method implementations which shouldn't be much harder than implementing your repository yourself in the first place.

Related

SDN doesn't work if I activate `-parameters` compiler's argument

I use Spring Data Neo4j 4.2.0.RELEASE and experience the following exception:
org.neo4j.ogm.exception.CypherException: Error executing Cypher "Neo.ClientError.Statement.ParameterMissing"; Code: Neo.ClientError.Statement.ParameterMissing; Description: Expected a parameter named 0
in the following place:
#Query("" +
"MATCH (u:User)-[:LOCATION]-(l:Location)-[r]-(p:PostalCode) " +
"WHERE id(u)={0} " +
"RETURN l, r, p"
)
Location findUserLocation(long userId);
in case if I use -parameters argument for my java compiler.
Do anyone know, why it may not work?
It's because compilation with -parameters allows the framework to get real parameter names from the source code.
In other words, it works the same way as : findUserLocation(#Param("userId") long userId)
Changing the query to use {userId} instead of {0} should work. If you need to be compatible with different compilation options, use #Param as stated above.

Apache Calcite: Convert a SQL parse tree into a tree of relational expressions WITHOUT validation

I'm currently working on a project in which I want to parse an SQL-Query and create the tree of relational expressions for it.
The main goal is to identify the join partners in the Queries.
So I'd like to push the join-expressions down to the leafs of the tree.
To achieve this, I decided to use Apache Calcite.
My code looks roughly like this at the moment:
Planner planner = Frameworks.getPlanner(Frameworks.newConfigBuilder().defaultSchema(Frameworks.createRootSchema(false)).build());
SqlNode parsed = planner.parse("SELECT s.dnasamplename, e.Total_expression_level, e.Soluble_expression_level, s.id " +
"FROM table1 e" +
"JOIN table2 s on s.constructname = e.Clone_name" +
"WHERE e.Total_expression_level like '0:%'");
planner.validate(parsed);
RelRoot relRoot = planner.rel(parsed);
If I try to execute the rel-Method of Planner directly, I get the error that I have to validate the query first. And that`s the point where I face troubles. I don't have a valid Schema. I just want to convert the query to a relational query plan. Is there a way to kind of skip the validation process?
It's not possible to skip the validation process. The sql-to-relational converter relies on state that has previously been created by the validator.
People see that the validator throws an exception if the SQL is invalid and imagine that this is its only purpose; but building the state is equally important. The state includes of a map of the type of each SqlNode, expansions of "*" and "tableAlias.*" in SELECT clauses, and fully-qualified identifiers.
If your schema is missing or incomplete, you might try a similar approach to Apache Drill. If the validator asks for a particular column of a table, and the table does not have that column, the Calcite namespace for that table says "yes, I have that column!" and adds it. Thus, the validation process succeeds, and each namespace has a list of the extra columns needed by the query.

what is the equelent of sql query in hibernate

In SQL Server i am using this query
select *
from Unit c
ORDER BY CONVERT(INT, LEFT(name, PATINDEX('%[^0-9]%', name + 'z')-1)) desc;
I want this query to use in Hibernate. when I use this in Hibernate I got error
java.lang.IllegalArgumentException: org.hibernate.hql.ast.QuerySyntaxException:unexpected token: LEFT near line 1, column 122
[SELECT c FROM models.entities.UnitEntity c WHERE c.expSetId = :expSetId AND isWaitArea=:isWaitArea ORDER BY CONVERT(INT, LEFT(name, PATINDEX('%[^0-9]%', name + 'z')-1)) asc]
some of that is not in the hibernate dialect, you can change left with substring, convert with cast. and as for patindex i couldn't find the substitution. you either can add pathindex to the constructor of the dialect that you use
registerFunction( "patindex", new StandardSQLFunction("patindex") );
or create patindex() to a stored procedure.
then you can use something like this:
from Unit c order by cast(substring(name, 0, PATINDEX('%[^0-9]%', name + 'z')-1) as integer);
or you can use locate() instead of patindex(), but i think it doesn't support regular expression.
I am pretty sure that you can use SQL query with hibernate as well. When you create your hibernate session, you can use something like
session.createSQLQuery("Your Query Here")
Hope this helps.

playframework use find with IN and a list of models

I've got a problem with the following code, written in play (1.2.4):
List<MSprache> sprachen = MSprache.find("active = ?", true).fetch();
List<MFieldDscr> textey = MFieldDscr.find("sprache IN", sprachen).fetch();
And if I execute a test, which tests this part of code, the following Error displays:
A java.lang.IllegalArgumentException has been caught, org.hibernate.hql.ast.QuerySyntaxException: unexpected token: null near line 1, column 48 [from models.Sprache.MFieldDscr where sprache IN]
I don't understand where the mistake is.
I'm not so sure about what you're trying to achieve,
but I think this is what you want:
String jpql = "FROM MFieldDescr fd WHERE fd.sprache "
+ "IN ( SELECT s FROM MSprache s WHERE s.active = ? ) ";
List<MFieldDscr> textey = MFieldDescr.find( jpql, true ).fetch();
This will find all the MFieldDescr entities which have a MSprache with active set to true.
The language used to query entities is JPQL by the way, in case you want to learn more about it.
Here are some useful links:
JPQL In Expressions
JPQL Subqueries

I need help with this error: java.lang.NoSuchMethodError

I have this Java code (JPA):
String queryString = "SELECT b , sum(v.votedPoints) as votedPoint " +
" FROM Bookmarks b " +
" LEFT OUTER JOIN Votes v " +
" on (v.organizationId = b.organizationId) " +
"WHERE b.userId = 101 " +
"GROUP BY b.organizationId " +
"ORDER BY votedPoint ascending ";
EntityManager em = getEntityManager();
Query query = em.createQuery(queryString);
query.setFirstResult(start);
query.setMaxResults(numRecords);
List results = query.getResultList();
I don't know what is wrong with my query because it gives me this error:
java.lang.NoSuchMethodError: org.hibernate.hql.antlr.HqlBaseParser.recover(Lantlr/RecognitionException;Lantlr/collections/impl/BitSet;)V
at org.hibernate.hql.antlr.HqlBaseParser.fromJoin(HqlBaseParser.java:1802)
at org.hibernate.hql.antlr.HqlBaseParser.fromClause(HqlBaseParser.java:1420)
at org.hibernate.hql.antlr.HqlBaseParser.selectFrom(HqlBaseParser.java:1130)
at org.hibernate.hql.antlr.HqlBaseParser.queryRule(HqlBaseParser.java:702)
at org.hibernate.hql.antlr.HqlBaseParser.selectStatement(HqlBaseParser.java:296)
at org.hibernate.hql.antlr.HqlBaseParser.statement(HqlBaseParser.java:159)
at org.hibernate.hql.ast.QueryTranslatorImpl.parse(QueryTranslatorImpl.java:271)
at org.hibernate.hql.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:180)
at org.hibernate.hql.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:134)
at org.hibernate.engine.query.HQLQueryPlan.(HQLQueryPlan.java:101)
at org.hibernate.engine.query.HQLQueryPlan.(HQLQueryPlan.java:80)
at org.hibernate.engine.query.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:94)
at org.hibernate.impl.AbstractSessionImpl.getHQLQueryPlan(AbstractSessionImpl.java:156)
at org.hibernate.impl.AbstractSessionImpl.createQuery(AbstractSessionImpl.java:135)
at org.hibernate.impl.SessionImpl.createQuery(SessionImpl.java:1650)
Thanks.
You definitely have an issue with the version of hibernate and ANTLR jars that you are using. The recover method wasn't present in the ANTLR Parser class until version 2.7.6? If you are using an earlier version of ANTLR, such as 2.7.2, then you will see this problem.
Using maven can cause this sort of situation, where you depend on Hibernate and its transitive dependencies, but something 'closer'; e.g. Struts; providers a different, earlier version of ANTLR and that earlier version gets resolved in your application.
If you can provide the version of jars involved, we would be able to help some more. Once you have fixed the issue with the jar versions, you should get a more revealing error message which shows what is wrong with your HQL expression.
Stab in the dark - Are you sure you have a consistent set of jars - perhaps you need to get the antlr jar that comes with the hibernate distribution you are using...
I've found the problem:
because this is a native query, java classes for this 2 tables must have some special attributes:
in Bookmarks.java class
#OneToMany(mappedBy = "bookmarkId")
private Collection votesCollection;
and in Votes.java class
#JoinColumn(name = "bookmark_id", referencedColumnName = "bookmark_id")
#ManyToOne
[private Bookmarks bookmarkId;
and i have also changed the query to work
tring queryString = "SELECT b, sum(v.votedPoints) " +
"FROM Bookmarks b " +
"LEFT OUTER JOIN b.votesCollection v " +
"WHERE b.userId = 101 " +
"GROUP BY b.organizationId " +
"ORDER BY sum(v.votedPoints) asc ";
thanks for the help
May be you have some double-quotes " missing or which should be doubled in your HQL.
Illustration here.
Or you miss some simple quotes as illustrated there
The query seems to be invalid unless it's an artifact of formatting.
I think you meant this:
Select b, ...
to be:
Select b.organizationId, ...
??
I have the consistent set of jars because simple queries like this one
"SELECT b FROM table_name b WHERE b.userId = 102 "
are working. I have verified all double quotes and everything is alright.
My database is: mysql, and I use jpa to connect to it. I don't know what is causing the problem. Maybe this type of join, i don't know
Er, isnt your query trying to select b which is a table alias and thats not allowed as far as I know.
I'd probably guess that something is going wrong with your query, because the method HqlBaseParser fails to lookup is called recover(RecognitionException, Bitset). Perhaps this query fails for some reason the other simpler queries don't (and the NoSuchMethod exception is thrown when attempting to recover from that error).
java.lang.NoSuchMethodError: org.hibernate.hql.antlr.HqlBaseParser.recover(Lantlr/RecognitionException;Lantlr/collections/impl/BitSet;)V
Your query is still wrong. Maybe it works with your driver/db but it isn't standard SQL. You should be selecting b.* or b.organizationId.

Categories