Java Hibernate Why executeUpdate on namedQuery executes full table update first? - java

I have a simple NamedQuery like this
#org.hibernate.annotations.NamedQuery(name="namedQuery",query="update entity set .... where id=:id"
I have a method like this
public void updateField(final Entity entity){
final Session session = currentSession();
final org.hibernate.Query query= session.getNamedQuery("namedQuery")
...loadParameters();
query.executeUpdate();
return;
}
This always works alright but sometimes in this line of code
query.executeUpdate();
Sometimes I see in the console a select from the entity like a full update of the entity. I don't understand why this happens; if I really want to update a simple field why Hibernate updates me all the fields? When this happens the only single update of the namedQuery seems useless because was I think was updated before.
Something like this i see this in the console
Hibernate:
/* update
com.models.Entity */ update
entity
set
BUNCH OF FIELDS
where
ID=?
and later I see what I really want the only field being updated
update
Entity
set
SINGLE_FIELD_UPDATE
where
ID=?
As I mentioned, the full update sometimes appears sometimes do not and sometimes the full update appears twice before the update of the namedQuery being executed!
Why is this? Why does Hibernate fire a full update and something twice the full update before the real field in the namedQuery being executed?
I am missing something?

Please annotate your class with
#org.hibernate.annotations.Entity( dynamicUpdate = true )
see here

Related

When using JPA2 EntityListener, how does it work if i use the in clause to update multiple rows?

query : update Order set f='1' where key in (1,2,3,4,5)
#PostUpdate
public void postUpdate(Order order) {
....
}
I wonder what happens if I work as above.
If you execute a bulk update/jpql update query of the from "update Order set f='1' where key in (1,2,3,4,5)" you get those rows affected and nothing else. JPQL bulk updates/deletes run in the database, so they do not affect your java entities and do not cause entity lifecycle events to occur.

How to update an entity with a condition(where clause) and get the updated entity in method response in spring data jpa

I am working on concurrent update handling stuff, my scenario is- an employee can be marked inactive from UI, but if once marked inactive, it should not be allowed to marked inactive again. I want to achieve it by making the db update call with a condition update entity where status=active. I need the updated entity in return.
How to update an entity with a condition(where clause) and get the updated entity in method response in spring data jpa
employeRepository.save(employee); // is it possible to do something like this with a condition at the same time update method returns updated entity.
You are working against the grain of JPA here.
I suggest you do it the JPA way:
load the entity
If the status property is not inactive set it to active.
When ever the transaction ends this will be written to the database.
If you insist on using an update statement
You can use the following process:
If the entity is part of the current session:
flush all changes to the database.
evict the entity from the session.
perform an update either using SQL or JPQL with a where clause like this: ... WHERE id = :id and status <> 'inactive'
use the id to load the entity again.
You can use JPQL.
uery query = entityManager.createQuery(
"UPDATE employee SET status = \"inactive\"" +
"WHERE status=\"active\"");
query.executeUpdate();
or just spring data
#Modifying
#Query("update employee u status = `inactive` where status=`active` and ...")
void disableUsers(...);
however, to deal with concurrent queries a good way could be Optimistic locking and #Version annotation.

Update entity in jpa

How can I update every fields in Entity without write sql query:
(update Entity u set u.m1= ?1, u.m2= ?2, ... where u.id = ?3)
Class has 20+ fields and if I write sql query This will take a long time. And I often add new fields
Can I update everything automatically? Like this:
entityRepo.update(entity);
If i do entityRepo.save(); create unnecessary record in base.
No, you can use JpaRepository.save(S entity) that saves or updates the entity if existing.
To achieve that, make sure that the entity has its JPA #Id valued before invoking save() otherwise a new record will indeed be created.
This is an alternative to #davidxxx's answer.
If the transaction with which the entity was fetched is not yet closed (i.e. the entity is still attached), you can simply update the java-object and the changes will be committed to the database when the transaction is committed.

Cannot get update query to work with Hibernate

I have a simple update query just to check if update query works:
this.openDBTransaction();
Query updateQuery = session.createQuery(
"UPDATE User AS usr SET usr.failedLogins=666 WHERE usr.id='USER_3000'"
);
int result = updateQuery.executeUpdate();
this.closeDBTransaction();
but somehow DB is not update with desired value. result came as 1 so something took place but for sure not update query.
Any clue what is going on?
You should use #Transactional annotation so that the compiler knows that the transaction is manipulating the database, thus permits to perform Data Manipulation queries or it will simply execute it as a Data Definition Language query.
Look at the code snippet below, for example,
#Transactional
public Employee editEmployee(Employee employee) { //employee is the data you got through post
return entityManager.merge(e1);
}
Also, the best practice is to always implement Data Access Object Interface and its implementation and define your queries in the implementation.
I hope this helps.

Hibernate/Spring HibernateTemplate.findByCriteria(Deatched Criteria dc) executes a sql update on view

I am trying to search a view based on given criteria. This view has a few fields for multiple different entities in my application that a user may want to search for.
When I enter the name of an entity I want to search for, I add a restriction for the name field to the detached criteria before calling .findByCriteria(). This causes .findByCriteria() to retrieve a list of results with the name I am looking for.
Also, when I look through my log, I can see hibernate calling a select statment.
I have now added another entity to my view, with a few searchable fields. When I try to search for a field related to this new entity, I get an exception in my log.
When I look through my log with the exception, I can see hibernate calling a select statment with an update statement right after the select (I am not trying to update a record, just retrieve it in a list).
So why is hibernate calling an update when I am calling .findByCriteria() for my new entity?
org.hibernate.exception.SQLGrammarException: Could not execute JDBC batch update
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:90)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:275)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:266)
SQL that is executed:
Hibernate:
select
*
from
( select
this_.SEARCH_ID as SEARCH1_35_0_,
this_.ST_NM as ST24_35_0_
from
SEARCH_RESULT this_
where
this_.LOAN_TYPE=? )
where
rownum <= ?
DEBUG 2012-03-21 11:37:19,332 142195 (http-8181-3:org.springframework.orm.hibernate3.HibernateTemplate):
[org.springframework.orm.hibernate3.HibernateAccessor.flushIfNecessary(HibernateAccessor.java:389)]
Eagerly flushing Hibernate session
DEBUG 2012-03-21 11:37:19,384 142247 (http-8181-3:org.hibernate.SQL):
[org.hibernate.jdbc.util.SQLStatementLogger.logStatement(SQLStatementLogger.java:111)]
update
SEARCH_RESULT
set
ADDR_LINE1=?,
ASSGND_REGION=?,
BASE_DEAL_ID=?,
ST_NM=?
where
SEARCH_ID=?
There is probably an update happening because Hibernate is set up to do an autoflush before executing the queries, so if the persistence context thinks it has dirty data, it will try to update it. Without seeing the code I can't be sure, but I'd guess that even though search_result is a view, your corresponding Java object is annotated on the getters and the object has matching setters. Hibernate doesn't make a distinction between tables and views, and if you call a setter, Hibernate will assume that it has data changes to update.
You can tweak how you build your Java objects for views by adding the #Immutable annotation (or hibernate.#Entity(mutable = false) depending on which version you're using. This should be enough to indicate to Hibernate to not flush changes. You can also annotate the fields directly and get rid of your setters so that consumers of the SearchResult object know that it's read only.

Categories