I am new to Hibernate. Please tell me what is the use of getHibernateTemplate().flush() and how it works.
When using Hibernate, entities are loaded into a persistence context called the session and changes like creating, updating, deleting persistent objects are actually made in memory. When you want or need to synchronize the in memory state with the database to make changes persistent, you need to flush the session, causing Hibernate to generate the appropriate SQL insert, update, delete statements.
Related
I deleted a record from the database, and the entity manager still references that deleted record.
I have the following query:
List results = em.createNamedQuery("Customers.findNew")
.setParameter("status", "n")
.getResultList();
I am getting back results which include the deleted record. I've read the entity manager caches the database for better performance. This is fine if only the application using the entity manager is accessing the database. But what happens when multiple systems will access the same database?
I have tried:
1. em.flush()
2. em.refresh()
3. em.clear()
right before I use entity manager to query the database, to try and force a re synchronization but none of them do. I am still getting the same record that isn't in the database anymore.
UPDATE
The program I used to delete record, Oracle SQL Developer, didn't commit changes. So JPA was working fine, it was the program I was using to make changes to the database hadn't committed the changes. If you are experiencing similar problem make sure the db admin program committed changes.
EntityManagers cache Objects themselves, for their own use. This is generally save.
In addition, you can enable the 2nd level cache, where inconsistencies can arise between systems. If you enabled this, try to disable it.
Did you delete the entity using the same EntityManager? If no, make sure the transaction to delete the entity is commited and make sure the transaction of your reading EntityManager starts after the deletion is commited.
Hibernate, as I know updates the Database once the attached Objects in the session's value changes. Is there a way to obtain a fresh copy from the database and reattach the fresh copy discarding the changed object?
Below is an object I obtained from Querying the Database using Hibernate.
Rtpmast rtpmast = (Rtpmast) iterator.next();
Once executed the below code
rtp.setRptval1(promotionMethod.getType());
Hibernate registers that the the object has changed. And when I commit a transaction later on or query the Database the Session is flushed?
What I want is to temporally update the Rtpmast object and discard the changed object later.
Hibernate, as I know updates the Database once the attached Objects
in the session's value changes.
Actually,Hibernate updates the database only after invoking session.save(...), session.delete(...) etc. methods. If you're in a transaction you'd also have to commit changes.
What you want is either use evict() and re-query the object, as you've mentioned, or detach the instance you're working on, which means you need to close() the Session (there are other, less trivial, ways to do so as mentioned here).
I am trying to understand how JPA works. From what I know, if you persist an Entity, that object will remain in the memory until the application is closed. This means, that when I look for a previously persisted entity, there will be no query made on the database. Assuming that no insert, update or delete is made, if the application runs long enough, all the information in it might become persistent. Does this mean that at some point, I will no longer need the database?
Edit
My problem is not with the database. I am sure that the database can not be modified from outside the application. I am managing transactions by myself, so the data gets stored in the database as soon as I commit. My question is: What happens with the entities after I commit? Are they kept in the memory and act like a cache? If so, how long are they kept there? After I commit a persist, I make a select query. This select should return the object I persisted before. Will that object be brought from memory, or will the application query the database?
Not really. Think about it.
Your application probably isn't the only thing that will use the database. If an entity was persisted once and stored in memory, how can you be sure that, let's say, one hour later, it won't be changed by some other means? If that happens, you will have stale data that can harm logic of your application.
Storing data in memory and hoping that everything will be alright won't bring any benefits. That's why data stored in database is your primary source of information, and you should query it every time, unless you are absolutely sure that a subset of data won't change.
When you persist an entity an entity this will add it to the persistence context which acts like a first level cache (this is in-memory). When the actual persisting happens depends on whether you use container managed transactions or deal with transactions yourself. The entity instance will live in memory as long as the transaction is not commited, and when it is it will be persisted to the database or XML etc.
JPA can't work with only the persistence context (L1 cache) or the explicit cache (L2 cache). It always needs to be combined with a datasource, and this datasource typically points to a database that persists to stable storage.
So, the entity is in memory only as long as the transaction (which is required for JPA persist operations) isn't committed. After that it's send to the datasource.
If the transaction manager is transaction scoped (the 'normal' case) then the L1 cache (the persistence context) is closed and the entities do not longer exist there. If the L1 cache somehow bothers you, you can manage it a bit explicitly. There are operations to clear it and you could separate your read operations (which don't need transactions) from write operations. If there's no transaction active when reading, there's no persistence context, an entity becomes never attached and is thus never put into this L1 cache.
The L2 cache however is not cleared when the transaction commits and entities inside it remain available for the entire application. This L2 cache must be explicitly configured and you as an application developer must indicate which entities should be cached in it. Via vendor specific mechanisms (e.g. JBoss Cache, Infinispan) you can put a max on the number of entities being cached and set/define so-called eviction policies.
Of course, nothing prevents you from letting the datasource point to an in-memmory embedded DB, but this is outside the knowledge of JPA.
Persistence means in short terms: you can shut down your app, and the data is not lost.
To achieve that you need a database or some sort of saving data in a way that it's not lost when you shut down the app.
To "persist" an entity means to actually save it in the data base. Sure, JPA maintains some entity information in memory in the persistence context (and this is highly dependent on configuration and programming practices), but at certain point information will be stored in the data base - for instance, when a transaction commits, or likely (but not necessarily) after flush() or merge() operations.
If you want to keep your entities after committing and for a select query, you need to use the query cache. Just Google around on that term and it should be clear to you.
we are developing an (JavaSE-) application which communicates to many clients via persistent tcp-connections. The client connects, performs some/many operations (which are updated to a SQL-Database) and closes the application / disconnects from server. We're using Hibernate-JPA and manage the EntityManager-lifecycle on our own, using a ThreadLocal-variable. Actually we create a new EntityManager-instance on every client-request which works fine so far. Recently we profiled a bit and we found out that hibernate performs a SELECT-query to the DB before every UPDATE-statement. That is because our entities are in detached-state and every new EntityManager attaches the entity to the persistence context first. This leads to a massive SQL-overhead when the server is under load (because we have an write-heavy application)and we try to eliminate that leak.
First, we thought about 2nd-Level-Cache. However, we discovered that hibernate invalidates it's Query- and Collection-Caches whenever a new item is added or removed.
On second thought, we evaluate whether to keep an EntityManager up as long as the client is logged in on the server. But I wonder if this is a "best practice", because there are some drawbacks: thread-safety, managing-overhead of the EntityManager-instances, etc.
In short: we are looking for a way to get rid of those SELECT-statements before every UPDATE. Any ideas out there?
One possible way to get rid of select statements when reattaching detached entities is to use Hibernate-specific update() operation instead of merge().
update() unconditionally runs an update SQL statement and makes detached object persistent. If persistent object with the same identifier already exists in a session, it throws an exception. Thus, it's a good choice when you are sure that:
Detached object contains modified state that should be saved in the database
Saving that state is the main goal of opening a session for that request (i.e. there were no other operations that loaded entity with the same id in that session)
In JPA 2.0 you can access Hibernate-specific operations as follows:
em.unwrap(Session.class).update(o);
See also:
11.6. Modifying detached objects
One possible option would be to use StatelessSession for the update statements. I've successfully used it in my 'write-heavy' application.
I'm gonna go with this design:
create an object and keep it alive during all web-app session.
And I need to synchronize its state with database state.
What I want to achieve is that :
IF between my db operations, that is, modifications that I persist to a db
someone intentionally spoils table rows, then on next saving to a database
all those changes WOULD BE OVERWRITTEN with the object state, that always contains valid data.
What Hibernate methods do you recommend me to use to persist the modifications in a database?
saveOrUpdate() is a possible solution, but maybe there's anything better?
Again, I repeat how it looks. First I create an object without collections. Persist it (save()).
Then user provides us with additional data. In a serviceLayer, again, we modify our object in memory (say, populate it with collections) and then, persist it again.
So every serviceLayer operation of the next step must simply guarantee that database contains the exact persistent copy of this object that we have in memory. If data in a database differ, it MUST BE OVERRIDDEN with the object (kept in memory) state.
What Session operations do you recommend?
FWIW saveOrUpdate() looks like the best option overall:
The saveOrUpdate() method is in practice more useful than update(),
save(), or lock(): In complex conversations, you don’t know if the item is in
detached state or if it’s new and transient and must be saved. The automatic
state-detection provided by saveOrUpdate() becomes even more useful when you
not only work with single instances, but also want to reattach or persist a network
of connected objects and apply cascading options.
However for your case, if you are sure the entity was modified in detached state, and/or don't mind occasionally hitting the DB with an unnecessary UPDATE, maybe update() is the safest choice:
The update() operation
on the Session reattaches the detached object to the persistence context and
schedules an SQL UPDATE. Hibernate must assume that the client modified the
object while it was detached. [...] The persistence context is flushed automatically
when the second transaction in the conversation commits, and any
modifications to the once detached and now persistent object are synchronized
with the database.
Quotes from Java Persistence with Hibernate, chapter 11.2.2.