QueryDsl and Embeddables with OneToMany | Wierd Generated SQL Select by "." - sql

I am expermenting querydsl with embeddable, on the following set:
#Entity
Class Ent1 {
#Embedded
Embed embed;
}
#Entity
Class Ent2 {
#ManyToOne
Ent1 ent1;
}
#Embeddable
Class Embed {
#OneToMany
List<Ent2> ent2List;
}
When i use following dsl query
query
.select(Projections.constructor(Embed.class, QEnt1.qEnt1.ent2List))
.from(QEnt1.qEnt1)
.fetch();
Generate this sql
select
. as col0,
ent2.ent1_id as col1
from
Ent1 ent1
inner join
Ent2 ent2
on ent1.id=ent2.id
following generated line breaks the query
. as col0
Sql works fine without generated dot line, any ideas how to fix ?
Note: Im using oracle sql

Related

Modify select identifiers in Sql Query using calcite

I want to modify a SQL query using Calcite. For example
SELECT values FROM data to
SELECT values as v FROM data
I could access SqlNode of select identifier using SqlVisiter implementation.
public Object visit(SqlCall sqlCall) {
SqlNodeList selectList = ((SqlSelect) sqlCall).getSelectList();
for (SqlNode sqlNode : selectList) {
System.out.println(sqlNode.toString());
}
Now what should I do to update SqlNode?
The SqlNode objects in the select list will be instances of SqlIdentifier in this case. So you'll have to cast sqlNode to a SqlIdentifier and then you can call .setName(0, "NEW_NAME"). After this, you call unparse on the original root node to get the new query back.

JpaRepository: Spring Sort for runtime query variabels

There is my plain sql query:
SELECT id, title,
IF(o.fixed_on_top = 1 AND o.fixing_on_top_day_counter > 5, 1 ,0) actual_fixed_on_top
FROM orders o
ORDER BY actual_fixed_on_top DESC, publication_date DESC;
How can I perform sorting like this on JpaRepository?
Maybe using Criteria API?
But I dint find any examples..
Thanks!
EDIT:
ok, studied different ways, and convinced that it cant be implemented through Criteria API (but it is a pity)
One working variant: Native SQL Query, i am sure.
You can do it by using the QueryDslPredicateExecutor which provides the following two method:
Iterable<T> findAll(Predicate predicate, OrderSpecifier<?> ... orderSpecifiers);
Page<T> findAll(Predicate predicate, Pageable pageable);
The PageRequest class implements Pageable and allows you to specified the sorting you want.
You could also add a Pageable parameter in a #Query annotated method on a regular JpaRepository and Spring Data Jpa will do the rest, for example:
#Query("select e from SomeEntity e where e.param1 = :param1")
public Page<SomeEntity> findSome(#Param("param1") String param1, Pageable pageable);
(sorry cannot comment yet)
I recently had the same issue.
The only solution worked for me, is to specify the order on the relationship.
I don't see a relationship in your query
example:
#OneToMany
#OrderBy("date")
...
Spring data jpa does understand order by see doc
findByAgeOrderByLastnameDesc() will be parsed into where x.age = ?1 order by x.lastname desc clause.
I see your case a bit complicated, but you can do JQPL with #Query annotation, Sample:
#Query("SELECT o FROM Order o WHERE write your clause ORDER BY o.something desc")
public Order findByCustomPK(#Param("paramIfNeeded"));
I found the solution:
public class MyEntitySpecifications {
public static Specification<MyEntity> GetByPageSpecification() {
return new Specification<MyEntity>() {
#Override
public Predicate toPredicate(Root<MyEntity> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {
Expression fixingExpr = cb.greaterThan(root.get(MyEntity_.fixingDueDate), new DateTime(DateTimeZone.UTC));
cq.orderBy(new OrderImpl(cb.selectCase().when(fixingExpr, 1).otherwise(0), false));
return cb...;
}
};
}
}
The main idea is using case expression instead of simple logical.
plain sql equuivalent is:
select ...
from my_entity e
where ...
order by case when e.fixing_due_date > now() then 1 else 0 end desc
So we can build dynamic queries with criteria api specifications as well.
No direct access to EntityManager, no plain sql.

How to use listagg in hibernate

I am trying to use listagg function to generate a list of users.
Consider the following table
ROLE_ID ENAME
---------- ----------
4 CLARK
4 KING
4 MILLER
7 ADAMS
9 FORD
9 JONES
On using the following query in the SQL Developer
SELECT ROLE_ID,
LISTAGG(ENAME, ',') WITHIN GROUP (ORDER BY ENAME) AS EMPLOYEES
FROM USERS
GROUP BY ROLE_ID;
will result in the following in the console output
ROLE_ID EMPLOYEES
-----------------------------
4 CLARK,KING,MILLER
7 ADAMS
9 FORD, JONES
My goal is try doing this in hibernate but I am not sure how to proceed.
Any help is appreciated.
For anyone having problems using listagg as part of a formula, registering the "within" keyword with Hibernate solved the problem for me. (Using Hibernate 5.0.7.)
public class CustomOracleDialect extends Oracle10gDialect {
public CustomOracleDialect() {
super();
registerKeyword("within");
}
}
Prior to this, Hibernate would break the query by attempting to prefix the "within" keyword with the outer table's alias. Once the keyword was registered the following works:
#Formula("(select (listagg(l.serial_number, ', ') within group(order by d.serial_number))\n"
+ "from order_lines l\n"
+ "where l.order_id = id\n"
+ "group by l.order_id)")
private String serialNumbers;
Note that if you try to assign an alias to the listagg expression it still breaks the query, as Hibernate tries to prepend it with the table's alias as well. This of course is not an issue with formula queries, but if using listagg as part of a named query you may need to omit the alias and reference the column by position within the result set.
We found a good solution.
#Formula("(select (listagg(l.serial_number, ', ') \00within group(order by d.serial_number))\n"
+ "from order_lines l\n"
+ "where l.order_id = id\n"
+ "group by l.order_id)")
private String serialNumbers;
Just append the \00 before WITHIN keyword.
And you don't need to extends anything.
Cheers.
Hibernate doesn't understand sql function be default. Try registering in hibernateDialect.
registerFunction("listAgg", new StandardSQLFunction("listAgg", Hibernate.STRING));
Registering of listagg method is not working in hibernate dialect . Try with registering wm_concat method , it worked for me ..
Find below code ..
public class ServiceAppOracle10gDialect extends Oracle10gDialect {
public ServiceAppOracle10gDialect() {
super();
//registerFunction("LISTAGG", new StandardSQLFunction("LISTAGG", StandardBasicTypes.STRING));
registerFunction("wm_concat", new StandardSQLFunction("wm_concat", StandardBasicTypes.STRING));
}
}
And make sure that u have changed your hibernate.dialect property ..
<!-- <prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop> -->
<prop key="hibernate.dialect">com.apple.sc.analytics.utils.ServiceAppOracle10gDialect</prop>
After a lot struggle i found this solution. I think it will help you all.You can register LISTAGG function like below
registerFunction("LISTAGG", new SQLFunctionTemplate( StandardBasicTypes.STRING,"LISTAGG(?1,',') WITHIN GROUP(ORDER BY ?1)"));
and you can use LISTAGG(<columnname>) in your hibernate query
To use listagg in hibernate query
First register listagg function in Hibernate Dialect by extending Oracle10gDialect(in case you are using Oracle) or MySQLDialect(for MySQL)
public class CustomOracle10gDialect extends Oracle10gDialect {
public CustomOracle10gDialect() {
super();
registerFunction("LISTAGG", new SQLFunctionTemplate(StandardBasicTypes.STRING,"LISTAGG(?1,',') WITHIN GROUP(ORDER BY ?1)"));
}
}
Update your config file to use custom dialect.
spring.jpa.database-platform=com.abc.CustomOracle10gDialect
or
com.abc.CustomOracle10gDialect
Use LISTAGG()
Example -
select c.id, listagg(firstName) from Contacts c where GROUP BY c.id

return objects that are not in the mapping file from nhibernate hql

the title says pretty much what I'm trying to do. I have nhibernate hql with select case
select application.SubmissionDate, count(candidates)
from Application as application group by application.SubmissionDate
I would like to have the return values from this query into an object (which is not in nhibernate mapping file) called 'CountPerDay' object
class CountPerDay {
public DateTime Date,
public int Count
}
does nHibernate has sort of build in feature /methods to do this?
You should take a look at Ad-hoc mapping for NHibernate:
string hql = #"select application.SubmissionDate as Date, count(candidates) as Count
from Application as application
group by application.SubmissionDate";
var count = session.CreateQuery(hql)
.SetResultTransformer(Transformers.AliasToBean(typeof(CountPerDay)))
.List<CountPerDay>();

How do I query for only superclass entities in a jpql query?

I have the following entities:
#Entity
#Inheritance(strategy=InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(name="orderType", discriminatorType=DiscriminatorType.STRING)
#DiscriminatorValue(value="BASE")
#Table(name = "orders")
public class OrderEntity implements Serializable {
...
and
#Entity
#DiscriminatorValue(value="RECURRING")
public class RecurringOrderEntity extends OrderEntity{
...
I can find all the subclasses (RecurringOrderEntity) with the following jpql:
Query q = em.createQuery(
"SELECT o from RecurringOrderEntity o where "
+ "o.cancellationDate is null "
+ "and o.maxOccurrences = o.occurrence");
What is the JPQL syntax for finding only entities that are not instances of RecurringOrderEntity?
I am using Eclipselink 2.0.0 as the JPA provider.
thanks!
What is the JPQL syntax for finding only entities that are not instances of RecurringOrderEntity?
Use an entity type expression with the TYPE operator. Something like this (not sure about the exact query you want but you get the idea):
SELECT o
FROM OrderEntity o
WHERE TYPE(o) <> RecurringOrderEntity
AND o.cancellationDate is null
AND o.maxOccurrences = o.occurrence
Below, the relevant section of the JPA 2.0 specification:
4.6.17.4 Entity Type Expressions
An entity type expression can be used
to restrict query polymorphism. The
TYPE operator returns the exact type
of the argument.
The syntax of an entity type
expression is as follows:
entity_type_expression ::=
type_discriminator |
entity_type_literal |
input_parameter
type_discriminator ::=
TYPE(identification_variable |
single_valued_object_path_expression |
input_parameter )
An entity_type_literal is
designated by the entity name.
The Java class of the entity is used
as an input parameter to specify the
entity type.
Examples:
SELECT e
FROM Employee e
WHERE TYPE(e) IN (Exempt, Contractor)
SELECT e
FROM Employee e
WHERE TYPE(e) IN (:empType1, :empType2)
SELECT e
FROM Employee e
WHERE TYPE(e) IN :empTypes
SELECT TYPE(e)
FROM Employee e
WHERE TYPE(e) <> Exempt