Is there any spring jpa equivalent to following query - java

Query :
#Query("Select p.name,t.points from Player p,Tournament t where t.id=?1 And p.id=t.player_id")
I have my player and tournament entity and their corresponding JPA repositories. But the problem is we can get only entities from our query, but i want to do above query, please help me with this i am new to it.
this is my sql query i want to add but where to add i am not getting:
Select p.name, t.points_rewarded from player p, participant t where t.tournament_id="1" and t.player_id=p.id;

This is how you can do it with JPQL for JPA:
String queryString = "select p.name, t.points from Tournament t," +
" Player p where t.player_id=p.id " +
"and t.id= :id_tournament";
Query query = this.entityManager.createQuery(queryString);
query.setParameter("id_tournament", 1);
List results = query.getResultList();
You can take a look at this JPA Query Structure (JPQL / Criteria) for further information about JPQL queries.
And this is ho you can do it using HQL for Hibernate, these are two ways of doing it:
String hql = "SELECT p.name, t.points from Player p,Tournament t WHERE t.id= '1' And p.id=t.player_id";
Query query = session.createQuery(hql);
List results = query.list();
Or using query.setParameter() method like this:
String hql = "SELECT p.name, t.points from Player p,Tournament t WHERE t.id= :tournament_id And p.id=t.player_id";
Query query = session.createQuery(hql);
query.setParameter("tournament_id",1);
List results = query.list();
You can take a look at this HQL Tutorial for further information about HQL queries.
Note:
In both cases you will get a list of Object's array List<Object[]> where element one array[0] is the p.name and the second one is t.points.

TypedQuery instead of normal Query in JPA
this is what i was looking for, thanks chsdk for help, i have to create pojos class, and in above link answer is working fine foe me,
Here is my code sample
String querystring = "SELECT new example.restDTO.ResultDTO(p.name,t.pointsRewarded) FROM Player p, Participant t where t.tournamentId=?1 AND t.playerId = p.id ORDER by t.pointsRewarded DESC";
EntityManager em = this.emf.createEntityManager();
try {
Query queryresults = em.createQuery(querystring).setParameter(1, tournamentId);
List<ResultDTO> result =queryresults.getResultList();
return new ResponseEntity<>(result, HttpStatus.OK);
} catch (Exception e) {
e.printStackTrace();
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
} finally {
if (em != null) {
em.close();
}}

Related

Trouble formulating a sql query in DAO Implementation using EntityManager.createQuery

I've method in my DAOImplwhich is intended to get a list of all books belonging to a specific user, from the database... The method looks like this:
#Override
public List<>BooksList> findListsOf(String userId) {
Query query = em.createQuery("SELECT * from BooksList where booksListOwner = unserid");
List<BooksList> resultsList = query.getResultList();
if (resultsList.isEmpty()) throw new NotFoundException();
return resultsList;
}
IntelliJ is showing me this error:
expression or DISTINCT expected, got '*'
What's wrong with my sql statement here?
BR,
Mic
You need to specify an identification variable rather than an SQL wilcard
List<BooksList> resultsList = em.createQuery(
"SELECT b from BooksList b where booksListOwner = :userId")
.setParameter("userId", userId)
.getResultList();

Custom Query Join in JPA using Criteria Builder API

Currently I am doing it like this:
List<Table1Entity> findAllMatchingEntities(Table1Entity table1Entity) {
String queryString = "SELECT table1.* FROM table1 "
+ "JOIN table2 t2 ON table1.id=t2.table1_id";
if (table1Entity.getName() != null) {
queryString +=" where name like ?";
}
Query query = em.createNativeQuery(queryString, Table1Entity.class);
if (table1Entity.getName() != null) {
query.setParameter(1, table1Entity.getName())
}
return query.getResultedList();
}
If I want to check more parameters in this join this will quickly turn into a lot of if statements and it would be really complicated to set parameters correctly.
I know I can check parameters with criteria Builder API like this:
if(table1Entity.getName() != null) {
table1EntitySpecification = (root, query, criteriaBuilder)
-> criteriaBuilder.like(
criteriaBuilder.lower(root
.get("name")),
("%" + table1Entity.getName() + "%")
.toLowerCase());;
}
and after that get them all with:
findAll(table1EntitySpecification) with findAll from simpleJPARepository. Now I can chain them together with .or or .and etc. and avoid setting the parameter and checking for null second time.
But how do I do join with criteria APi?
I know I can have in my #Repository something like this:
#Query(value = "SELECT table1.* FROM table1 JOIN table2 t2 ON table1.id=t2.table1_id", nativeQuery = true)
List<Table1Entity> findAllMatchingEntities(Table1Entity table1Entity);
But since name is optional (can be null) I can't just leave it in #Query.
What is the best solution here to avoid using native query and in case of having to check many parameters to avoid using if statements?
I don't know if I fully get your question, but regarding the possibility of nulls, and using the CRUD repository, you can always do a null check before like:
#Query(value = "SELECT table1.* FROM table1 JOIN table2 t2 ON table1.id=t2.table1_id WHERE table1.id is not null", nativeQuery = true)
List<Table1Entity> findAllMatchingEntities(Table1Entity table1Entity);
Depending on what you are trying to achieve, you can always compose the query with similar checks like (not related to your code):
#Query("SELECT c FROM Certificate c WHERE (:id is null or upper(c.id) = :id) "
+ "and (:name is null or upper(c.name) = :name)")
List<Table1> findStuff(#Param("id") String id,
#Param("name") String name);

Hibernate createNativeQuery - get more than one Entity

I am using following code to execute native SQL query with hibernate:
Query zonesQuery = session.createNativeQuery(
"Select * \n" +
"FROM dbo.Structure AS S\n" +
"JOIN dbo.StructureLocationType AS SLT ON SLT.StructureId = S.Id\n" +
"WHERE SLT.LocationTypeId = :lc").addEntity(StructureEntity.class);
zonesQuery.setParameter("lc", locationTypeID);
List<StructureEntity> zones = zonesQuery.list();
So it works and it gets me list of StructureEntity
now, because my sql query "join" from StructureLocationType table, is there possibility to get whole StructureLocationType row as well, still using single query?
Thank you.
It can be achieved with the following (notice curly braces in SQL and entities aliases):
Query query = session
.createNativeQuery(
"SELECT {S.*}, {SLT.*} " +
"FROM dbo.Structure AS S " +
"JOIN dbo.StructureLocationType AS SLT ON SLT.StructureId = S.Id " +
"WHERE SLT.LocationTypeId = :lc")
.unwrap(SQLQuery.class)
.addEntity("S", StructureEntity.class)
.addEntity("SLT", StructureLocationTypeEntity.class)
.setParameter("lc", locationTypeID);
List<Pair<StructureEntity, StructureLocationTypeEntity>> result = ((List<Object[]>) query.list())
.stream()
.map(p -> Pair.of((StructureEntity) p[0], (StructureLocationTypeEntity) p[1]))
.collect(Collectors.toList());
You can't get multiple Objects from one query.
But you could either select which columns you want and then iterate the returned Object array:
The query:
SELECT s.id, s.someColumn, slt.id, slt.structureId
FROM dbo.Structure AS s
JOIN dbo.StructureLocationType AS slt on slt.structureId = s.id
WHERE slt.locationTypeId = :lc
Then iterate over the Object array:
List<Object[]> result = query.getResultList();
Or you could create a view on your database and map it to a java entity using the Table annotation like it was a normal table:
#Entity
#Table(name = "STRUCTURE_LOCATION_TYPE_VIEW")
public class StructureAndLocationType {
// ...
}
I thought there is a way to map from a query to an Object without creating a DB view but couldn't find it right now.

java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to className

Code:
public void getDetails() {
try {
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
String hql = "select c.mobile, c.password FROM CrbtSubMasterDemo c where rownum<20";
Query query = session.createQuery(hql);
List<CrbtSubMasterDemo> itr = query.list();
session.getTransaction().commit();
for (CrbtSubMasterDemo pojo : itr) {//excepion line
System.out.println("[" + pojo.getMobile() + "]");
}
} catch (Exception e) {
e.printStackTrace();
}
}
CrbtSubMasterDemo is pojo mapped with the db.
When I try to run it, it gives following Exception:
java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to com.telemune.demoPojo.CrbtSubMasterDemo
at com.telemune.demoHibernate.QueryTester.getDetails(QueryTester.java:57)
at com.telemune.demoHibernate.QueryTester.main(QueryTester.java:23)
The question is query.list() is returning the list of objects of pojo class. Then why is this Exception. I am new to Hibernate, sorry if its a silly question.
When you write this:
String hql = "select c.mobile, c.password FROM CrbtSubMasterDemo c where rownum<20";
Your result set is not a List of CrbtSubMasterDemo
Try to write:
String hql = "select FROM CrbtSubMasterDemo c where rownum<20";
Another way is define a new constructor of CrbtSubMasterDemo where you pass only two fields c.mobile, c.password
so your query becomes:
String hql = "select new " + CrbtSubMasterDemo.class.getName() + "(c.mobile, c.password) FROM CrbtSubMasterDemo c where rownum<20";
If you follow this solution, remeber to add a default constructor too (without parameters), so in your pojo you have:
public CrbtSubMasterDemo(String mobile, String password) {
this.mobile = mobile;
this.password = password
}
and
public CrbtSubMasterDemo() {
}
String hql = "select c.mobile, c.password FROM CrbtSubMasterDemo c where rownum<20";
Query query = session.createQuery(hql);
Result of this will be List<Object[]>
List<Object[]> itr = query.list();
for (Object[] row : itr) {
System.out.println(String.format("mobile:%s, password:%s", row[0], row[1]));
}
if mobile and password are strings, of course. You can use a transformer to transform results directly to CrbtSubMasterDemo.
Hibernate 3.2: Transformers for HQL and SQL
FluentHibernateResultTransformer
Sir, Many times user faces this kinda requirements . Hibernate has ResultTransformer to convert a hql/sql in Object.
public CrbtSubMasterDemo{
private Stirng mobile;
private String password;
public CrbtSubMasterDemo(){
--------------
}
#####after setting the transation set whichever columns you are selecting should be given as name of property of your object
String hql = "select c.mobile as mobile, c.password as password FROM CrbtSubMasterDemo c where rownum<20";
Query query = session.createQuery(hql);
List<CrbtSubMasterDemo> itr = query.setResultTransformer(Transformers.aliasToBean(CrbtSubMasterDemo.class) ).list();
##No need to commit the transaction.
}
It will convert you query into the CrbtSubMasterDemo
Do not directly cast the result of "query.list();" to List of CrbtSubMasterDemo. As query.list() return object list. Iterate over the object list received and cast one by one to put in list List of CrbtSubMasterDemo

Hibernate query for searching part of string

I'm trying to write a hibernate query to search if table Room contains roomname which contains part of string.The string value is in a variable. I wrote a query to get exact room name from the table.
findRoom(String name) {
Query query = em.createQuery("SELECT a FROM Room a WHERE a.roomname=?1");
query.setParameter(1, name);
List rooms = query.getResultList();
return rooms;
}
In sql the query is something like this:
mysql_query("
SELECT *
FROM `table`
WHERE `column` LIKE '%"name"%' or '%"name"' or '"name"%'
");
I want to know the hql query for searching the table that matches my query. I can not use string directly, so the search query has to be veriable based and I need all three types in a query, if it's begin with name, or contains name or ends name.
I would do something like that:
findRoom(String name) {
Query query = em.createQuery("SELECT a FROM Room a"
+ "WHERE a.roomname LIKE CONCAT('%',?1,'%')");
query.setParameter(1, name);
List rooms = query.getResultList();
return rooms;
}
Use like instead of =:
Query query = em.createQuery("SELECT a FROM Room a WHERE a.roomname like ?1");
query.setParameter(1, "%"+name+"%");

Categories