How to call Named Query - jpa

I wrote a named query in the entity class Voter
NamedQuery(name = "Voter.findvoter", query = "SELECT count(*) FROM Voter v WHERE v.voterID = :voterID" and where v.password= : password),
I want to call this named query and I also need to set voterID and password.
Can you help me. Thank you

I assume you've missed the # symbol on your NamedQuery annotation?
In the code, you'd call it like this:
List results = em.createNamedQuery("Voter.findvoter")
.setParameter("voterID", "blah")
.setParameter("password","blahblahblah")
.getResultList();

There are two obvious issues with your named query that would cause a problems:
It is an annotation so it should be #NamedQuery not just NamedQuery
Your query is currently:
query = "SELECT count(*) FROM Voter v WHERE v.voterID = :voterID" and where v.password= : password.
The problem is that you terminate your String after :voterID, instead of after :password and you have "where" twice and you have a space between ":" and "password". Your query should look like this:
query = "SELECT count(*) FROM Voter v WHERE v.voterID = :voterID and v.password= :password"
(I have just moved the " to the end and removed the second "where" and the space after the ":")

The common steps are (named query or otherwise)
Create a query - em has five create methods.
Set the query up with parameters if needed - the query interface has these methods.
Execute the query - the query interface has 3 execution related methods.
with the above three steps you can run any JPA query.

Actually brent is right your NameQuery should be something like this,
#NamedQuery(name = "Voter.findvoter", query = "SELECT count(*) FROM Voter v WHERE v.voterID = :voterID AND where v.password = :password")
#Entity
public class Voter implements Serializable{ ... }
and somewhere else you should try this one (which Dick has already said)
public class VoterFasade{
public List<Voter> findVoter(long id,String password){
List<Voter> results = em.createNamedQuery("Voter.findvoter")
.setParameter("voterID", id)
.setParameter("password",password)
.getResultList();
return result;
}
}
then you could use it like
#Inject
VoterFasade voterFasade;
///
long id=12;
voterFasade.findVoter(id);
should actually working.(its an uncompiled code).
you could also do it with Repository, check the link below, part Repository Listing23.Example repository
enter link description here

Related

How pass value with #Param annottaion to a method

I decided move all my jpql queries to another class, for example
public class QueryUtils {
public static final String FIND_All_CLUBS= "select c from Club c order by c.club_name";
}
In repository I have this:
#Query(value = QueryUtils.FIND_All_CLUBS)
Iterable<Club> findAllAndAndOOrderByClub_name();
And it works fine. But I'm stuck with that thing : what if I have params in my jpql, f.e.
#Query(value = "select c from Comment c where c.post.post_id = :id order by c.replyTo.comment_id nulls last")
Iterable<Comment> findAllCommentsOfPost(#Param("id") long id);
I'm tried to write this:
public static String getFIND_ALL_COMMENTS_OF_POST(String id){
return new StringBuilder("select c from Comment c where c.post.post_id = ").append(id).append(" order by c.replyTo.comment_id nulls last").toString();
}
But how pass param from repository to this method, this code(which I tried is not valid):
#Query(QueryUtils.getFIND_ALL_COMMENTS_OF_POST(id))
Iterable<Comment> findAllCommentsOfPost(#Param("id") long id);
Pls, help me!!
Alternative to #Param, try this one
#Query(value = "select c from Comment c where c.post.post_id = ?1 order by c.replyTo.comment_id nulls last")
Iterable<Comment> findAllCommentsOfPost(long id);

Spring JPA repository casting error when using JPQL

I have a PagingAndSorting JPA repository declared. I am using the #Query annotation.
I am getting an exception when I call the get() method on an Optional object from the findById(id) method of the repository.
The weird thing is it only happens when I use JPQL.
The code works if my query is native:
#Override
public BatchDto findById(String id) {
Optional<Batch> findResult = this.batchRepository.findById(id);
if (!findResult.isPresent()) return null;
Batch entity = findResult.get(); **<-------- Cast Exception Here**
BatchDto dto = this.mapper.toDto(entity, BatchDto.class);
List<BatchTransaction> transactions = entity.getTransactions();
dto.setTransactionDtos(mapper.toListDto(transactions, TransactionDto.class));
return dto;
}
Inspecting the findResult object with a breakpoint - I can see:
Optional[net.domain.data.batch#4b8bb6f]
when I have nativeQuery = true in the #Query annotation.
#Query(value = Sql.FindBatchById, nativeQuery = true)
Here is the query being used:
SELECT DISTINCT(B.batchNumber), COUNT(B.batchNumber) as TransactionCount FROM BATCH B WHERE B.batchReferenceNumber = :id GROUP BY B.batchNumber
However if I change it to JPQL and remove the nativeQuery=true attribute - the findResult is
Optional[[Ljava.lang.Object;#76e04327].
and I get a ClassCastException:
java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to net.domain.data.batch
So bottom line - this works when specify nativeQuery=true and fails when I try to use JPQL.
I would prefer not to specify nativeQuery as we will eventually port this db to Oracle.
First of all the query shown below doesn't return a single Batch instance. Since there are distinct and count aggregate functions, the query will return a List of aggregates.
To be able to read that statistics you can add appropriate method into the batchRepository. Something like this:
#Query("SELECT DISTINCT(B.batchNumber) as dist, COUNT(B.batchNumber) as cnt FROM BATCH B GROUP BY B.batchNumber")
List<Map<Long, Long>> findStatistics();
and then iterate through the list.
UPD
If the id parameter exactly guarantee that will return a single record, you can change a return type to a Map
#Query("SELECT DISTINCT(B.batchNumber) as dist, COUNT(B.batchNumber) as cnt FROM BATCH B WHERE B.batchReferenceNumber = :id GROUP BY B.batchNumber")
Map<Long, Long> findStatisticsById(#Param("id") Long id);

JPA eclipselink global batch fetch?

when joining I get one select per row. Solution is batch fetch but I dont want that annotation everywhere...
http://eclipse.org/eclipselink/documentation/2.4/jpa/extensions/a_batchfetch.htm
Why do I even need this? One select per row is awful... How can I set this globally? Cheers
Maybe not the ideal solution, but you may try to use JPA hints along with Java generics:
public <T> TypedQuery<T>
createBatchQuery(String ql, Class<T> clazz, String type, String size, String relation) {
return em.createQuery(jpql, clazz)
.setHint(QueryHints.BATCH_TYPE, type)
.setHint(QueryHints.BATCH_SIZE, size)
.setHint(QueryHints.BATCH, relation);
}
The above query may then be used globally and extended with concrete query implementations according to you needs, i.e.
String jpql = "SELECT c FROM Country c WHERE c.name = :name"; // or #NamedQuery
TypedQuery<Country> q = createBatchQuery(jpql, Country.class, "JOIN", "64", "c.cities");
q.setParameter("name", "Australia");
Country c = q.getSingleResult();
Articles on this topic:
Batch fetching - optimizing object graph loading
EclipseLink/Examples/JPA/QueryOptimization

playframework selecting from h2 database

I am trying downloading all records from table in h2 buildin database in playframework.
I am facing an error:
[IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: * near line 1, column 8 [SELECT * FROM TABLE]]
Method CODE i class Table:
#Transactional(readOnly=true)
public static Result view() {
Query query = JPA.em().createQuery("SELECT * FROM TABLE");
List<Table> downloaded_from_db = query.getResultList();
System.out.println(downloaded_from_db.getClass());
return ok(view.render("none"));
}
Please help me. I would like to see downloaded records in console in simple view.
Please give me some tips or good tutorial.
After changing my class loooks like this:
#Transactional(readOnly=true)
public static Result view() {
List<MedicalIncidents> data = JPA.em()
.createNativeQuery("SELECT * FROM MedicalIncident")
//.createQuery("Select m from MedicalIncident m")
.getResultList();
System.out.println(data);
AND I think it works, cause I have 2 entries in that table in database:
But System.out.println(data) return in plaay console:
[[Ljava.lang.Object;#70a0c9be, [Ljava.lang.Object;#4c1d12b6]
But it should return this object by model name like in example: computer-database-jpa:
[models.Computer#214c6fde, models.Computer#63728eb3, models.Computer#75f6bcc6, models.Computer#19e3a7ab, models.Computer#3114d8d4, models.Computer#4fa75f78, models.Computer#756ce822, models.Computer#40fc4c68, models.Computer#73fc612c, models.Computer#3e4fcb31]
So I think that there is something wrong with it. Please help
You mxied SQL queries with JPQL query. The method you used createQuery needs an JPQL query:
SELECT e FROM Entity e
Also please note in JPQL there is no SELECT *. If you want to write a SQL query, use the method em.createNtiveQuery().

Cannot create TypedQuery for query with more than one return

I am using the following JPA query and i am getting the java.lang.IllegalArgumentException: Cannot create TypedQuery for query with more than one return Exception.
TypedQuery<RaBdrRating> uQuery =
(TypedQuery<RaBdrRating>)entityManager.createQuery("
SELECT r.activePackage,SUM(r.duration),SUM(r.charge),COUNT(r)
FROM RaBdrRating r WHERE r.callType = :callType
and r.startDate between :startDate and :endDate
GROUP BY r.activePackage",RaBdrRating.class);
uQuery.setParameter("callType", model.getCallType());
uQuery.setParameter("startDate",startDate);
uQuery.setParameter("endDate",endDate);
List<RaBdrRating> listOfPackages = uQuery.getResultList();
Can any one tell me what is wrong in my query.....I am new to JPA and i am not getting what is the problem and strucked up here.If any one have idea please tell me.
I go the same error:
Cannot create TypedQuery for query with more than one return using requested result type
Solution:
Having a Query like this:
Select e.fieldA, e.fieldB, e.fieldC From Entity e
You have to declare a constructor with the parameters specified on query:
package somepackage;
public class Entity {
...
public class Entity() {}
public class Entity(Type fieldA, Type fieldB, Type fieldC) {
this.fieldA = fieldA;
this.fieldB = fieldB;
this.fieldC = fieldC;
}
....
}
Finally, modify your query
Select NEW somepackage.Entity(e.fieldA, e.fieldB, e.fieldC) From Entity e
You are indicating how the objectes will be created.
This seems to be this bug: https://hibernate.onjira.com/browse/HHH-6304
It is apparently fixed in version 4.1.5.