selecting maximum field of a column using query dsl predicate - java

Im new to query dsl.Im using Spring repositories to get the result set.And one case i have to get the maximum of a column and get the fields in to an entity.My predicate code is below.I get error once i run this code.
public static Predicate getMaximum(){
QUserDetails details = QUserDetails.userDetails;
return details.id.eq(details.id.max());
}
And this is how i fetch my resultset using spring jpa
public UserDetails findByCustomerId(Predicate predicate);
And this is the error i get:
org.springframework.data.mapping.PropertyReferenceException: No property find found for type com.example.entity.UserDetails.Can anyone help me acheive what i want here.

You have to define a QueryDslJpaRepository which adds implementation for QueryDslPredicateExecutor
http://docs.spring.io/spring-data/jpa/docs/1.5.0.M1/api/org/springframework/data/jpa/repository/support/QueryDslJpaRepository.html
You can see a tutorial here:
http://www.petrikainulainen.net/programming/spring-framework/spring-data-jpa-tutorial-part-eight-adding-functionality-to-a-repository/

From the QueryDSL email group, apparently what you have to do to select the max ID is this:
from(entity).singleResult(entity.id.max())
So it's
JPAQuery jpaQuery = new JPAQuery(entityManager);
QEntity qEntity = QEntity.entity;
Long maxId = query.from(qEntity).singleResult(qEntity.id.max());

Related

GenericJDBCException: could not extract ResultSet

I found similar questions about this error but I can't make it work
I'm working on a java 8, spring 2.6.4 and a MySQL database
I'm trying to do a DELETE native query using JPA and I'm getting this error:
org.springframework.orm.jpa.JpaSystemException: could not extract ResultSet; nested exception is org.hibernate.exception.GenericJDBCException: could not extract ResultSet
this is my query:
#Query(value = "DELETE FROM reservation a WHERE a.slotid =:slotid", nativeQuery = true)
void deleteWhereSlotid(Integer slotid);
and this is the service:
repo.deleteWhereSlotid(reservationSlot.getId());
I've also tried:
#Query(value = "DELETE FROM reservation a WHERE a.slotid =:slotid", nativeQuery = true)
Object deleteWhereSlotid(Integer slotid);
//service
Object object= userCourseResRepo.deleteWhereSlotid(reservationSlot.getId());
but it failed
Usually I delete rows with deleteById(id) which comes with spring
The query works though, I tried it on phpMyadmin console and it worked
Someone know what I can try?
The way you have it set up, Spring Data assume you want to perform a query (typically a SELECT). For DELETE and similar statements that don't return a ResultSet you need to provide an additional #Modifying annotation.
#Modifying
#Query(value = "DELETE FROM reservation a WHERE a.slotid =:slotid", nativeQuery = true)
void deleteWhereSlotid(Integer slotid);
I know is not the best solution, but you can try to use a query SELECT to find your reservation object and then do this repo.deleteById(reservation.getId())
This should allow you to go ahead while you find a better way to do it
If you are using it that way, I believe the query should be:
DELETE a FROM reservation a WHERE a.slotid =:slotid
I am not particularly sure about the code, however, with Mysql, the case seems to be so when giving an alias to the table.
You need to add #Param
#Query(value = "DELETE FROM reservation a WHERE a.slotid =:slotid", nativeQuery = true)
Object deleteWhereSlotid(#Param("slotid")Integer slotid);
As mentioned above, we use the #Param annotation in the method declaration to match parameters defined by name in JPQL/Native query with parameters from the method declaration.

Using querydsl with undetermined schema with mongo and spring boot

I've the following mapping:
#Document
class Event {
Object carbonCopy;
}
carbonCopy has several attributes and its schema is undetermined - various events can have different set of attributes. Assume that carbonCopy has status field. I need to find all Events that have carbonCopy.status equal to NEW. Is it possible with query DSL, how? I'm struggling with various mixes of Path and Expression instances to no avail.
You can use similar like
in terminal
db.events.find({"carbonCopy.status":"NEW"})
in termilnal if you need existance as well
db.events.find({carbonCopy.status:{"$exists":true}},"carbonCopy.status":"NEW"})
NOW when it comes to SDM
Criteria criteria = Criteria.where("carbonCopy.status").is("NEW")
Query query = new Query(criteria);
return mongoTemplate.findOne(query, Event.class);
Criteria criteria = Criteria.where("carbonCopy.status").is("NEW").And("carbonCopy.status").exists(true)
Query query = new Query(criteria);
return mongoTemplate.findOne(query, Event.class);
It's possible with the following piece of code:
QEvent event = QEvent.event;
PathBuilder<Event> query = new PathBuilder<Event>(Event.class, "entity");
BooleanExpression expr = query.getMap("objectCarbonCopy", String.class, String.class).get("status").eq(Expressions.constant("NEW"));
Where QEvent is querydsl generated class.

Query in spring data mongo repository

I want to write custom query on spring data mongodb. Something like this:
public interface CarRepo extends MongoRepository<Car, String> {
#Query("select distinct(brand) from Car ")
public List<String> findDistinctBrand();
}
But it's throwing an error "Caused by: com.mongodb.util.JSONParseException: ". How can I achieve that?
MongoDB does not support distinct command.
It only supports returning distinct field values using the distinct command.
You need to use Mongodb template, for your results:
DBCollection colllection = mongoTemplate.getCollection("collectionName");
Criteria criteria = new Criteria();
criteria.where("your column").is("your value");
Query query = new Query();
query.addCriteria(criteria);
List list = mongoTemplate.getCollection("collectionName")
.distinct("source",query.getQueryObject());
You are using SQL to query in mongodb, but mongodb has its own query language. You need to write query in that language. As you are going to use distinct command you cannot user Query annotation or spring data query to do that. You need to create custom repository and execute distinct command using MongoTemplate.
Per the docs you should be able to accomplish this by simply defining the method in your repository interface, without the help of #Query:
public interface CarRepo extends MongoRepository<Car, String> {
public List<String> findDistinctBrand();
}

Spring Data JPA with QueryDSL, Count issue with aggregate function

I am using Spring Data JPA with QueryDSL and trying to use Sum function in where condition, As i am using pagination so i have to get count first.
So i have java code like below :-
NumberPath<Double> path = entityPath.getNumber("qty", Double.class);
BooleanExpression exp = path.sum().loe(120);
JPQLQuery countQuery = from(stock).where(exp);
long count = countQuery.count();
its creating query like this :-
select count(stock0_.stock_id) as col_0_0_ from stock stock0_
where sum(stock0_.qty)>=120;
and i am getting Error Code: 1111. Invalid use of group function.
above query is not working in SQL as well because sum function cant be use with count in where condition. I have not idea how to deal with such problem when i have to get count first and then fetch the real data.
Can someone please help me out with what is JPA approach to deal with such issue.
Please don't suggested #Query annotation because i can not use it. Due to dynamic filtration requirement.
You are using aggregate functions (sum). Then you need having() instead where()
This example is a really large one. You only need to care about pagination and having elements.
If you got different predicates and a pageRequest object.
Page request example:
pageRequest = new PageRequest(
MI_PAGE,
LIMIT,
Sort.Direction.valueOf( ASC ),
ORDER_FIELD);
EntityQ represents a QueryDSL generated meta-entity.
Query example:
new JPAQuery(em).from(entityQ).where( entityQ.id.in(
new JPASubQuery()
.from(entity2Q).innerJoin(entity2Q.objEntityQ, entityQ)
.where(ENTITY, PREDICATE)
.groupBy(entity2Q.objEntityQ.id)
.having( Wildcard.count.goe(SIZE) )
.list(entity2Q.objEntityQ.id)
))
.offset(pageRequest.getOffset() )
.limit( pageRequest.getPageSize() )
.orderBy(ORDERS).list(entityQ);
EDIT 2 More specific for your example:
I usually have a persistence context in my custom repositories:
#PersistenceContext
EntityManager em
Then, you could create a simple JPAQuery:
new JPAQuery(em)
.from(YOUR_STOCK_QUERYDSL_ENTITY)
.groupBy(YOUR_STOCK_QUERYDSL_ENTITY.field_to_sum)
.having(YOUR_STOCK_QUERYDSL_ENTITY.field_to_sum.sum().as("alias")
.goe(100));

JPQL Native Query using SUM and COUNT

I am trying to run the following code:
public BigDecimal valuate(String searchTerms, String categoryPath) {
Query query = em.createNativeQuery("SELECT SUM(maxBidAmount) / COUNT(maxBidAmount) FROM Item WHERE MATCH(title) AGAINST(':searchTerms') AND categoryPath=':categoryPath'", Double.class);
query.setParameter("searchTerms", searchTerms);
query.setParameter("categoryPath", categoryPath);
double value = (double) query.getSingleResult();
return new BigDecimal(value);
}
When I do so, I get the following exception:
Exception Description: Missing descriptor for [class java.lang.Double].
When I remove Double.class, I get a different exception.
So, I'm just wondering the correct method of using COUNT and SUM with JPQL.
IF the SQL is valid, you do not need to specify the Double.class in the query def - just use em.createNativeQuery(SQLString);
The return type is used when you want the JPA provider to build an entity from the results, but in this case you want the raw data.
Native query is SQL, not JPQL, and you use those keywords just like any SQL for your RDBMS.
Looks like your JPA provider doesn't accept Double as a result class (some only allow the result class to be an Entity).
DataNucleus JPA certainly allows non-Entity result classes.

Categories