Parameter not bound in Hibernate Query - java

I tried to make a query withSpring data for updating an entry by id and I tried a lot options but still I can't get rid of this:
Named parameter not bound : table.eventDate
#Modifying
#Query(value = "update Table_name u set u.id = :table.id, u.event_date = :table.eventDate, u.client_id = :table.clientId, u.status = :table.status, u.status_date = :table.statusDate, u.creation_date = :table.creationDate, u.last_update_date = :table.lastUpdateDate where u.id = :table.id",
nativeQuery = true)
void updateEntity(#Param("table") Table table);
How should I write the query in order to get rid of this?
I tried a lot of posibilities online to write the query but nothing worked.

Correct native query statement:
#Modifying
#Query(value = "update Table_name u set u.id = :table.id, u.event_date = :table.event_date, u.client_id = :table.client_id, u.status = :table.status, u.status_date = :table.status_date, u.creation_date = :table.creation_date, u.last_update_date = :table.last_update_date where u.id = :table.id",
nativeQuery = true)
void updateEntity(#Param("table") Table table);
Since you're using a native query instead of a JPQL-Query, you have to write :table.event_date instead of :table.eventDate. Same counts for example :table.clientId, it has to be :table.client_id.
Hope it'll work!
Native Queries: Always snake_case instead of camelCase, unless your column names are in camelCase, but I doubt that. :)

Related

Solve JPQL Query

I am trying to get details of Properties details from database using JPQL, Hear I am writing where condition like (properties.IsDeleted <> 'Y' or properties.IsDeleted IS NULL)
but, in JPQL query it is not getting 'Y', but, it is was showing like '?' symbol. this is the problem I am getting. please help me from this issue.
the below code is showing query like:-
select properties0_.property_id as col_0_0_,
properties0_.property_type as col_1_0_, properties0_.property_name as
col_2_0_, properties0_.property_area as col_3_0_,
properties0_.property_city as col_4_0_, properties0_.no_of_rooms as
col_5_0_ from iot_property properties0_ where
(properties0_.is_deleted<>? or properties0_.is_deleted is null) and
properties0_.property_id=6
In the above query in bold mark shows properties0_.is_deleted<>? ,but what I want is properties0_.is_deleted<>Y
why that "Y" is not assigned to that query. that I am not understanding.
will you please help me to solve this issue.
Thanks
CriteriaBuilder deviceBuilder = propertySession.getCriteriaBuilder();
CriteriaQuery<Object[]> userCriteriaQuery = deviceBuilder.createQuery(Object[].class);
Root<Properties> propertyRoot = userCriteriaQuery.from(Properties.class);
Path<Object> pathPropertyId = propertyRoot.get("propertyId");
Path<Object> pathpropertyType = propertyRoot.get("propertyType");
Path<Object> pathpropertyName = propertyRoot.get("propertyName");
Path<Object> pathpropertyArea = propertyRoot.get("propertyArea");
Path<Object> pathpropertyCity = propertyRoot.get("propertyCity");
Path<Object> pathnumberOfRooms = propertyRoot.get("numberOfRooms");
userCriteriaQuery.multiselect(pathPropertyId, pathpropertyType, pathpropertyName, pathpropertyArea,
pathpropertyCity, pathnumberOfRooms);
Predicate userRestriction = deviceBuilder.or(deviceBuilder.notEqual(propertyRoot.get("isDelete"), "Y"),
deviceBuilder.isNull(propertyRoot.get("isDelete")));
Predicate userRestriction2 = deviceBuilder
.and(deviceBuilder.equal(propertyRoot.get("propertyId"), propertyId));
userCriteriaQuery.where(deviceBuilder.and(userRestriction, userRestriction2));
Query<Object[]> deviceQuery = propertySession.createQuery(userCriteriaQuery);
List<Object[]> resultList =deviceQuery.getResultList();
for(Object[] objects : resultList) {
Integer dbPropertyId = (Integer) objects[0];
String dbPropertyType = (String) objects[1];
String dbpropertyName = (String) objects[2];
String dbpropertyArea = (String) objects[3];
String dbpropertyCity = (String) objects[4];
Integer dbNoOfRooms = (Integer) objects[5];
System.out.println(dbPropertyId);
System.out.println(dbPropertyType);
System.out.println(dbpropertyName);
System.out.println(dbpropertyArea);
System.out.println(dbpropertyCity);
System.out.println(dbNoOfRooms);
}
There is no such thing as "the final JPQL that ultimately gets translated to the final SQL with inserted paramerters". How a JPA implementation generates the SQL is down to it, and parameters, in general, will never be substituted into any String. SQL has generated from expression trees etc, not a String. This is a criteria query so for parameters it will show "?" on the console.
If you want param values inserting in then do it yourself since it only makes sense to you

Why is the first Query working and the second not? (Spring application JPA)

I have two Query's that I want to use in a Spring project (using JPA). The first one gets an account and this works correctly. For the second one I want it to be able to update the 'disabled' field in the database. The codes look like this:
// This is the first Query (works correctly)
#Query(value = "SELECT * FROM accounts WHERE email = ?1", nativeQuery = true)
Account findByEmailAddress(String emailAddress);
// This is the second Query (doesn't work)
#Modifying
#Query(value = "UPDATE accounts SET disabled = 1 WHERE email= ?1 ", nativeQuery = true)
int disableAccountByEmail(String emailAddress);
I did read somewhere I needed to add #Modifying and this will return an int or void. But when I try to test if it works I get a TransactionRequiredException error that says: Executing an update/delete query
Try using the below for update query
#Transactional
#Modifying(clearAutomatically = true)

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);

Equivalent of `set #variable = 0` in spring data jpa

I am trying to execute following queries in one go on MySQL through spring data jpa.
SET #i := 0;
UPDATE tv_episode te SET te.display_episode_no= #i:=#i+1 WHERE te.tv_season_id=season ORDER BY broadcast_date;
I tried finding out a solution for this on StackOverflow, but couldn't find any.
What is the equivalent of SET #i := 0; in spring-data-jpa? Is there a way I can execute the statement in #Modifying & #Query annotated method?
You can run native queries by adding nativeQuery = true to #Query :
#Modifying
#Query(value = "SET #i := 0;\n" +
"UPDATE tv_episode te SET te.display_episode_no= #i:=#i+1 WHERE te.tv_season_id = :season", nativeQuery = true)
int updateUserSetStatusForName(#Param("season") Integer season);
And If you don't want to use native query you can pass parameters like this:
#Modifying
#Query("update TvEpisode te set te.displayEpisodeNo = :epiodeNo where te.tvSeasonId = :season")
int updateUserSetStatusForName(#Param("epiodeNo") Integer epiodeNo,
#Param("season") Integer season);

problem with HQL update

When I try to execute the following HQL query:
Query query = getSession().createQuery("update XYZ set status = 10");
query.executeUpdate();
I get this exception:
Exception in thread "main" org.hibernate.QueryException: query must begin with SELECT or FROM: update
EDIT:
I also tried following .But it doennot work either.
org.hibernate.Query query = getSession().createQuery("update XYZ t set t.status = 10");
EDIT2:
Making changes in hinbernate.cfg.xml solved my problem
Earlier i was using
setting hibernate.query.factory_class" = org.hibernate.hql.classic.ClassicQueryTranslatorFactor
Now am using following property
<property name="hibernate.query.factory_class">org.hibernate.hql.ast.ASTQueryTranslatorFactory</property>
Thats not an HQL query.
You want to import javax.persistence.Query which allows normal sql,
not org.hibernate.Query which works on entity objects.
If you want to use simple sql, you could also use PreparedStatement
However, if you really want to use hibernate, without taking advantage of entityobjects (totally defeating the point of using hibernate in the first place, imho) you could do it like this (reference docs):
String myUpdate = "update XYZ myAlias set myAlias.status = :newStatus";
// or String noAliasMyUpdate = "update XYZ set status = :newStatus";
int updatedEntities = getSession().createQuery(myUpdate) //or noAliasMyUpdate
.setInt( "newStatus", 10 )
.executeUpdate();
The question is thinking in SQL, when you should be thinking in objects:
XYZ xyz = new XYZ();
xyz.setStatus(10);
getSession().merge(xyz);
Try:
Query query = getSession().createQuery("update XYZ o set o.status = 10");
query.executeUpdate();
Take a look at this also.
Session sesssion = getSession(); //getter for session
For HQL :
String hql = "update Activity " +
"set startedOn = :taskStartedOn " +
"where id = :taskId";
Query query = session.createQuery(hql);
query.setDate("taskStartedOn",new Date());
query.setLong("taskId",1)
int rowCount = query.executeUpdate();
Here Activity is POJO.
Use
hibernate.query.factory_class = org.hibernate.hql.ast.ASTQueryTranslatorFactory
in hibernate.cfg.xml file to resolve exception:
org.hibernate.QueryException: query must begin with SELECT or FROM: update.....

Categories