I have a need to track he state change of a java entity class that uses MySQL as its database. I know the EntityManager has a mechanism to track state change for the entities it is managing. What I want is to access the entity state change. I want my application to fire an even to inform another application regarding the the new state of the entity. From what I gathered so far, there is no API that I can use to check the particular life-cycle an entity is in. Or is there?
Does any one have information on how to approach this?
JPA defines listener interfaces, that you can implement in order to be notified of lifecycle events for the entities.
Have a look at this article: http://www.objectdb.com/java/jpa/persistence/event
EclipseLink provides a set of events at the session level (SessionEventListener).
I assume you only want to notify of committed changes, after they have been committed? For this you can use the postCommitUnitOfWork event. The event/uow contain a UnitOfWorkChangeSet that contains the list of changes that were made in the transaction.
Related
My application uses Hibernate/Spring/Struts/MySql.
The requirements are:
Log the HQL queries w.r.t user SessionId.
Revert/rollback statements on demand.
Intention is to quickly log the changes user does to data and also revert instantly if needed. I am not sure about the feasibility of such.
Yes, you can. The fist, look at hibernate-envers project. This project helps you to make changes audit. Its creates audit table for every entity table and fills it automatically when entities has been changed. But the second part of task, I suppose, you can do only manually: in audit tables will be stored all entities changes. Then you can simply revert data in entity to the last version.
Transactions are ACID and they are durable. Rolling back a committed transaction is not possible, because there might be other transactions already using the state state you changed.
You probably want a CQRS architecture, where events are stored in the data base (solving the audit logging requirement too) and the changes are replayed by a batch processor.
The easiest way to revert an action is by submitting a compensatory event.
Good day everyone,I have Java application that use JPA (EclipseLink) for database access-some CRUD operation.How i can make synhronization in that case ? I mean if two users User1 and User2 start application on they machine and User1 change some records how to make User2 see it ? Is there some opportunity make User2 know that User1 change record and update only that record ?. The same problems has discussed here How to synchronize multiple clients with a shared database (JPA)?. Updated data (in Database) is not visible via JPA/Eclipselink
But the only what there suggest is to update by timer. Is it common way to do such things ?
Thank you for your help
[EDIT]
Monitor MySQL inserts from different application How to make a database listener with java? change notification on domain objects (Hibernate/Java)
Show me direction in resolving my problem .Hope can help somebody.
You should create a new entity Manager instance for each transaction. I suggest to use spring with a JTA Transaction manager and let the container manage the entity manager scope.
See http://spring.io/blog/2011/08/15/configuring-spring-and-jta-without-full-java-ee/
[edit]
Note that if there is a refreh(someEntity) method on the EntityManager, there is no refreshAll() method. This is because the EM is not designed to last a long time and be refreshed.
If you let the container (Spring is advised for a standalone app) manage the persistence context (container managed entityManager), it will instantiate a new EM for each transaction. In other words, each time you invoke a method annotated with #transactional annotation, a new EM will be instantiated for the lifecycle of the method.
In this case you don't need to take care about data synchronization, each time you want the grid to be refreshed you recall the transactional getMyEntityList() method which will retrieve a new fresh set of entities to display in the grid. You can of course use a timer to trigger the refresh.
The trick is to never let unpersisted modification in memory. Each time a user update the grid, open a new transaction and persist the modification, each time you refresh, retrieve a new up-to-date persistence context and let the GC dispose the old unreferenced entities.
If you don't want user1 to be able to override user2 data, configure optimistic locking.
Otherwise if you absolutely want to maintain an application scoped EM for performance reason (avoiding to regularly retrieve data for DB), you can set up a messaging topic for the different application instance to notify each others in case of data update, but this gonna lead to additional work and constraints.
I'm writing an application (a CMS) using JPA/Hibernate, and in a single UI i have multiple components that might show the same entity (each one will show only a portion). I also have multiple UIs, in multiple sessions for multiple users.
Some of these components can also edit the entity, and all others component should always show the up-to-date entity.
A gross way would be a periodic refresh, but this is laggy and heavy, so i come up with a synchronization mechanism for jpa.
Using an interceptor (the hibernate one, since the jpa one is dumb) i can listen all the transactions, all the new/updated/removed entity and send notifications to every component interested in.
I also can catch derived transactions, meaning that if a component, responding to a notification, modify in any way the entity (opening a new transaction) i can resend the notification (only a delta).
This is becouse a component may modify the entity in a such way that another component may need to modify again it. (just a stupid example: a component set the birth date, and another re-calculate the age)
ps. The notifications are dispatched only after the transaction commit. This is mainly becouse
The section 3.5 of JPA specification states:
“In general, the lifecycle method of a portable application should not invoke EntityManager or Query operations, access other entity instances, or modify relationships within the same persistence context. A lifecycle callback method may modify the non-relationship state of the entity on which it is invoked.”
so the listeners would be useless if notified inside the transaction.
And (to grin and bear it) to group up modified entities and notify them all together.
This notification mechanism is growing complex, and i was wondering:
Why jpa has not such mechanism?
I'm inventing something strange?
How "real applications" solves this problem?
In a Spring based application I want to update some database (MySQL) tables whenever one table is updated. The logic is complex so I cannot depend on database triggers. I want to implement the logic in Java. I have the code to trigger functions. I came across Spring Custom Events and was considering using them to make the code more structured.
I was thinking whenever table1 is updated in a Repository instance it triggers an event which also updates another table. Right now inside a Repository I have an #Autowired repository for other database tables which need to be invoked manually. Can I get a more structured implementation logic?
The documentation says the events are synchronous. What is the order of invocation of event listeners invoked?
Can I end up in cycles? How do I prevent cycles? Any simple ideas.
Edit: I guess cycles will not be a problem as long as I do not publish another event in the listener.
As an aside I have an #Autowired entity manager instance in all the repositories. Are these entity manager instances all the same in all the Repositories? Here is the configuration file looks like.
Edit: I am asking this to understand if I need to persist all the objects to the same entity manager instance in order to be part of the same transaction. My entity manager instance is annotated #PersistenceContext. Am I correct in assuming that the entity manager has a singleton scope when declared using annotations.
Edit: Just in case it is helpful I have #Transactional annotation on all Repository classes.
Describe please a typical lifecycle of a Hibernate object (that maps to a db table) in a web app.
Suppose, you create a new instance of an object and persist in the db.
But during the app lifetime you'll be working on a detached object and finally
you need to update it in the database, for example on exit.
How does it look like with hibernate and spring?
p.s. Can transactions and sessions live between servlet transitions? So that we opened 1 session and use it in all servlets without a need to reopen it?
I'll try to give a descriptive example.
Suppose, when the app starts, the log record is created. this can be done at once,
Log log = new Log(...) and then something like save(log) -- log corresponds to a table LOG.
then, as the application processes user inputs and keeps going, new data is being accumulated.
and after the second step we could add something to a log object, a collection for example:
// now we have a tracking of what user chosen: Set thisUserChoice,
// so we can update the persistent object, we have new data now !
// log.userChoices = thisUserChoice.
Here occurs the nature of my question. How are we supposed to deal with it, if we want to
update the database whenever new data is gotten from a user?
In a relational model we can work with a row id, so we could get this record and update some other data of the row.
In Hibernate we are also able to load a object by its id.
But is IT THE WAY TO GO? IS ANYTHING BETTER?
You could do everything in a single session. But that's like doing everything in a single class. It could make sense from a beginner's point of view, but nobody does it like that in practice.
In a web app, you can normally expect to have several threads running at once, each dealing with a different user. Each thread would typically have a separate session, and the session would only have managed instances of the objects that were actually needed by that user. It's not that you can completely ignore concurrency in your own code, but it's useful to have hibernate's help. If you were to do everything with one session, you would have to do all the concurrency management yourself.
Hibernate can also manage the concurrency if you have multiple application servers talking to a single database. The separate JVMs can't possibly share the same session in this case...
The lifecycle is described in the hibernate documentation (which I'm sure you've seen).
Whenever a request comes from the web client to the server, the first thing you should do is load the relevant objects (see section 10.3) so that you have persistent, not detached entities to deal with. Then, you do whatever operations are required. When the session closes (ie. when the server returns the response to the client), it will write any updates to the database. Or, if your operation involves creating new entities, you'll have to create transient ones (with new) and then call persist() or save() (see section 10.2). That will result in a managed entity -- you can make more changes to it, and hibernate will record those changes when the session closes.
I try to avoid using detached objects. But if I have to (perhaps they're stored in the user's session), then whenever they might need to be saved to the database, you'll have to use update() (see section 10.6). This converts it into a managed object, and so the session will save any changes to the database when it's closed.
Spring makes it very easy to generate a new session for each request. You would normally tell Spring to create a sessionFactory, and then every request will be given its own session. Search for "spring hibernate tutorial" and you'll find several examples.
http://scbcd.blogspot.com/2007/01/hibernate-persistence-lifecycle.html This explains transient, persistent objects.
Also have a look at the Lifecycle interface to know what hibernate does (and it provides hooks at all stages for user to do something)