Win a copy of OCP Oracle Certified Professional Java SE 11 Programmer I Study Guide: Exam 1Z0-815 this week in the Programmer Certification forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Liutauras Vilda
  • Junilu Lacar
  • Jeanne Boyarsky
  • Bear Bibeault
Sheriffs:
  • Knute Snortum
  • Devaka Cooray
  • Tim Cooke
Saloon Keepers:
  • Tim Moores
  • Stephan van Hulst
  • Tim Holloway
  • Ron McLeod
  • Carey Brown
Bartenders:
  • Paweł Baczyński
  • Piet Souris
  • Vijitha Kumara

How to properly use EntityManager when Adding and Removing Items from Table?

 
Greenhorn
Posts: 12
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
**How to properly use EntityManager when Adding and Removing Items from Table?**
 ----

Im currently working with Hibernate And JavaFX.

My question is:
I have this JavaFX table that holds Fruit.class Objects. Im adding and removing objects on this table and when I click Save, I want to update the database.
How should I design the use of the EntityManager?
Am I supposed to hold the EntityManager open while this screen is opened? According to some posts, I should open and close the EntityManager for each transaction done. However, In this case, the 'transaction' involves adding and removing 0...n Fruit.class Objects.

In another words, the user might add and remove Fruits before saving.

How do I correctly approach this, regarding the EntityManager?



Also, for the Undo action, can I use audit tables from hibernate?


[![enter image description here][1]][1]
 
----



 [1]: https://i.stack.imgur.com/b85Nv.png
 
Saloon Keeper
Posts: 21266
138
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I use Spring JPA and for that, the EntityManager is injected into each of my DAOs. So it exists for the life of the app.

In any event, I can't see creating and destroying an EntityManager for each transaction if you're going to run a series of transactions one after another.

I'd be doubtful about using audit tables as a rollback mechanism. Databases are not really "undo-able" platforms, and most of their ability to negate a transaction after it has been committed requires extreme measures, often including action by the DBA. Instead they go more on the "are you sure?" approach, where if there's any doubt, you cancel the transaction and roll it back.

If you do have an app where "undo" on persistent data is needed, I'd recommend making the app deal with it. You can, for example, maintain your own undo tables.

In some cases, you might enter data into transaction tables where periodically they'd get applied to the primary tables. This is something that financial systems, for example, often do. In such cases, you have a limited amount of time to change your mind before the transaction is applied. Once that happens a counter-transaction would have to be entered to undo things.
 
Sheriff
Posts: 6374
172
Eclipse IDE Postgres Database VI Editor Chrome Java Ubuntu
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
A small point on your JavaFX code:

The interface Intializable has been deprecated.  In your case that's fine since you don't use the location or resources parameters.  So your method can just be
 
Castiel Snow
Greenhorn
Posts: 12
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Tim Holloway wrote:I use Spring JPA and for that, the EntityManager is injected into each of my DAOs. So it exists for the life of the app.

In any event, I can't see creating and destroying an EntityManager for each transaction if you're going to run a series of transactions one after another.

I'd be doubtful about using audit tables as a rollback mechanism. Databases are not really "undo-able" platforms, and most of their ability to negate a transaction after it has been committed requires extreme measures, often including action by the DBA. Instead they go more on the "are you sure?" approach, where if there's any doubt, you cancel the transaction and roll it back.

If you do have an app where "undo" on persistent data is needed, I'd recommend making the app deal with it. You can, for example, maintain your own undo tables.

In some cases, you might enter data into transaction tables where periodically they'd get applied to the primary tables. This is something that financial systems, for example, often do. In such cases, you have a limited amount of time to change your mind before the transaction is applied. Once that happens a counter-transaction would have to be entered to undo things.



Thanks Tim Holloway and Knute Snortum for the reply.

Knute, I didnt know about that, fixed already Thanks!!!

Tim Holloway, If I use Spring, would I be able to Undo the last action?
Also, I was looking into using the audit tables to rollback and they seemed fine. I was thinking the admin would have a way to choose the revision and merge the old data to the new Entity.

Hm, Do you have any suggestions except that one for periodic transactions?
Im having issues on my old app where users would miss-delete an object and wanted to revert what he done.


Also, I really appreciate your replies, this forum is way more friendly than StackOverFlow. Im liking here way more than SO and I feel more welcome.
Thanks.

Also, If im not abusing much, Would be okay to link my repo for you guys to take a look? Im coding alone and Im working on this example app to leave public in hope it might help others to start with Hibernate and JavaFx.







 
Tim Holloway
Saloon Keeper
Posts: 21266
138
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Spring doesn't have any database "undo" that I know of. Then again, I'm basing that on how databases work. So that's not the definitive answer.

If mis-deletions are the issue, though, what I'd do is define "deleted" tables that are subclasses of the primary tables (or something like that), and simply move the record(s) over when deleting or move them back to their primary tables when un-deleting.

OR

You could add a delete flag (and maybe userid/timestamp) to the affected table and hide deleted records from the standard operations. To un-delete, you'd simply reverse the delete flag column value. That's actually the way that most database apps do it.

A lot of database apps actually don't even support physical deletion. Instead they go for years until either people switch to something different or someone (probably the DBA) goes in and does a mass cull of all the deadwood.
 
Tim Holloway
Saloon Keeper
Posts: 21266
138
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Likes 2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Castiel Snow wrote:
Also, I really appreciate your replies, this forum is way more friendly than StackOverFlow. Im liking here way more than SO and I feel more welcome.
Thanks.



It's one of our most fundamental rules, although as far as I'm aware we're actually older than SO.

StackOverflow is a great place to go when you need something to plug into your system NOW, but it does have its problems, most infamously being told that the question was already answered elsewhere (often, alas, not quite the same question), or shouldn't have been asked in the first place. They've been working hard on making it less so, but it's a struggle. At least, however, you won't get flamed there, which was a MAJOR problem in many earlier forums, where you'd not only get insulted for daring to post the question, but for even having the audacity to be alive in the first place.

Which was one of the reasons why we're so insistent on "be nice". And why we don't permit "handles", since we've found that people are less prone to be abusive if they can't hide their identity. So we pride ourselves on our civility here.

Still, the main difference between the Ranch and SO is, as I said, SO is where you find working (we hope!) answers and that's good when you need something fast. But here on the Ranch, we specialize in explaining the reasons for the answers. Because if you know the "what", you're OK for the current problem, but if you know the "why" you can solve a whole class of problems all by yourself.
 
Castiel Snow
Greenhorn
Posts: 12
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Tim Holloway wrote:

Castiel Snow wrote:
Also, I really appreciate your replies, this forum is way more friendly than StackOverFlow. Im liking here way more than SO and I feel more welcome.
Thanks.



It's one of our most fundamental rules, although as far as I'm aware we're actually older than SO.

StackOverflow is a great place to go when you need something to plug into your system NOW, but it does have its problems, most infamously being told that the question was already answered elsewhere (often, alas, not quite the same question), or shouldn't have been asked in the first place. They've been working hard on making it less so, but it's a struggle. At least, however, you won't get flamed there, which was a MAJOR problem in many earlier forums, where you'd not only get insulted for daring to post the question, but for even having the audacity to be alive in the first place.

Which was one of the reasons why we're so insistent on "be nice". And why we don't permit "handles", since we've found that people are less prone to be abusive if they can't hide their identity. So we pride ourselves on our civility here.

Still, the main difference between the Ranch and SO is, as I said, SO is where you find working (we hope!) answers and that's good when you need something fast. But here on the Ranch, we specialize in explaining the reasons for the answers. Because if you know the "what", you're OK for the current problem, but if you know the "why" you can solve a whole class of problems all by yourself.



Hi Tim!
Thanks for the reply.
Yeah well, I also had issues on SO and some troll started to downvote my posts..

~~~~~

If im not abusing much, Would be okay to link my repo for you guys to take a look?
Im coding alone and Im working on this example app to leave public in hope it might help others to start with Hibernate and JavaFx.
I want to leave this repo in public with good practices for people who are starting with javaFx and Hibernate and jPackage . I struggled so hard and couldnt find good working examples.

I think the add/remove is a bit slow. Am I doing something wrong? I set up c3po and the batch mode, but no luck. Seems 'persist' takes a little more time than what I expected.


https://github.com/KenobySky/hellofx

 
Tim Holloway
Saloon Keeper
Posts: 21266
138
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The only objection I have to external links is if they are spam (which isn't something github is known for). It's better when possible to include (small) code samples directly on the Ranch, though. External links, alas, often end up pointing to long-vanished web locations.

As I said, my EntityManager is injected (via Spring) directly into each of my DAO classes and remains there for the life of the application. Since you are constantly creating and destroying EntityManagers, I suspect that a lot of the overhead is in there. If an EntityManager is creating Connections, I can virtually guarantee it. For my webapps, my EntityManager is linked to a Connection Pool owned by the webapp server, so there is very low overhead for me.

Just as a note, I don't recommend creating things in one place and destroying them in another. It can lead to maintenance problems. Or resource leakage. Or both.
 
Castiel Snow
Greenhorn
Posts: 12
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Tim Holloway wrote:The only objection I have to external links is if they are spam (which isn't something github is known for). It's better when possible to include (small) code samples directly on the Ranch, though. External links, alas, often end up pointing to long-vanished web locations.

As I said, my EntityManager is injected (via Spring) directly into each of my DAO classes and remains there for the life of the application. Since you are constantly creating and destroying EntityManagers, I suspect that a lot of the overhead is in there. If an EntityManager is creating Connections, I can virtually guarantee it. For my webapps, my EntityManager is linked to a Connection Pool owned by the webapp server, so there is very low overhead for me.

Just as a note, I don't recommend creating things in one place and destroying them in another. It can lead to maintenance problems. Or resource leakage. Or both.



" I don't recommend creating things in one place and destroying them in another. It can lead to maintenance problems."

Do you mean the DAO? Not sure how else I would make it.
 
Tim Holloway
Saloon Keeper
Posts: 21266
138
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Well, again, I inject the EntityManager into the DAO once and forever. But if you feel obliged to include the EntityManager in your DAO call, you should have the calling code do the deletion, not the DAO code.

Here again, I don't recommend creating and destroying multiple EntityManagers. Aside from the overhead, transactions can only belong to one EntityManager, so if you start doing things like persisting parent/child relationships and you have a separate DAO for the parent and the child. having two EntityManagers would result in much unpleasantness. Conversely, if you pass the same EntityManager to both DAOs and the first one destroys the EntityManager internally, the second DAO is going to have a hard time.
 
Bartender
Posts: 1200
38
IBM DB2 Netbeans IDE Spring Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Tim Holloway wrote:Well, again, I inject the EntityManager into the DAO once and forever. But if you feel obliged to include the EntityManager in your DAO call, you should have the calling code do the deletion, not the DAO code.

Here again, I don't recommend creating and destroying multiple EntityManagers. Aside from the overhead, transactions can only belong to one EntityManager, so if you start doing things like persisting parent/child relationships and you have a separate DAO for the parent and the child. having two EntityManagers would result in much unpleasantness. Conversely, if you pass the same EntityManager to both DAOs and the first one destroys the EntityManager internally, the second DAO is going to have a hard time.


This answer makes me think a lot.Generally, in a Spring context , I used to inject an EntityManager via @PersistentContext annotation. This way, one gets actually a proxy from an EntityManager factory, and now that you wrote that, I realize I never verified if, for each method annotated with @Transactional, a fresh entity manager is created from the factory. I think that it should be so, because @PersistentContext should be thread safe.
What do you think, Tim ?
 
Tim Holloway
Saloon Keeper
Posts: 21266
138
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I have pondered things of that nature many times and the only good answer I could come up with was "It just works". But actually, this is what the JavaDocs say about EntityManager:

https://docs.oracle.com/javaee/7/api/javax/persistence/EntityManager.html wrote:
An EntityManager instance is associated with a persistence context. A persistence context is a set of entity instances in which for any persistent entity identity there is a unique entity instance. Within the persistence context, the entity instances and their lifecycle are managed.



Alas, as in so many other instances, this isn't as precise as I'd like it to be, but the way I read it is that basically one EntityManager should manage ALL the Entities for a given database (or more specifically a JDBC URL). In fact, that would imply that the EMF createEntityManager may be returning a singleton for everybody. Note that I don't cover situations where multiple databases are involved, and thus multiple EntityManagers. I'll leave that as an exercise.

Another fuzzy definition is EntityManager.getTransaction(). Which

may be used serially to begin and commit multiple transactions.



It doesn't actually say what happens in a multi-threaded environment if two different threads want to run a transaction concurrently. Possibly the second thread is blocked?? And the rules differ depending on whether you have container-managed (e.g., EJB) transactions or resource-local transactions.

As far as that goes, however, beginning a transaction makes work "thread-safe" in any event, since once a transaction is begun, the affected objects are effectively locked for the duration of the transaction.

Obviously if I wanted to really understand it all, I'd need to do more reading. But since no one is currently paying me for even the stuff that I know works, I'm going to have to put it on the Curiosity Pile. Too many other things I need to learn for work at hand.
 
Claude Moore
Bartender
Posts: 1200
38
IBM DB2 Netbeans IDE Spring Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Tim Holloway wrote:

It doesn't actually say what happens in a multi-threaded environment if two different threads want to run a transaction concurrently. Possibly the second thread is blocked?? And the rules differ depending on whether you have container-managed (e.g., EJB) transactions or resource-local transactions.

As far as that goes, however, beginning a transaction makes work "thread-safe" in any event, since once a transaction is begun, the affected objects are effectively locked for the duration of the transaction.

Obviously if I wanted to really understand it all, I'd need to do more reading. But since no one is currently paying me for even the stuff that I know works, I'm going to have to put it on the Curiosity Pile. Too many other things I need to learn for work at hand.



Maybe I found an answer, at least for Spring, reading docs and experimenting a bit.
Let's say you inject an entity manager in a @Service class, like this:



having configured somewhere in your code an LocalContainerEntityManagerFactoryBean instance to register a EntityManagerFactory in your Spring application: the LocalContainerEntityManagerFactoryBean instance in responsible for creating all the EntityManagers you're going to inject.
What you actually get, is a SharedEntityManagerCreator instance, that is more or less a sophisticated proxy able to delegate all method calls to the entity manager registered in your service or in your DAO to an EntityManager which is bound to the current transaction - i.e, one Entity Manager per transaction,
or to a newly created EntityManager if no transaction is running.

From Spring's documentation:

A shared EntityManager will behave just like an EntityManager fetched from an application server's JNDI environment, as defined by the JPA specification.  It will delegate all calls to the current transactional EntityManager, if any; otherwise it will fall back to a newly created EntityManager per operation.

Stepping into the code - while debugging a sample project - I was able to verify that for each transaction a different EntityManager is created: you need to annotate with @Transactional the methods where you are using the entity managers.
So, I would conclude that for practical purposes using an EM is thread safe, with proper use of transaction boundaries.
 
Tim Holloway
Saloon Keeper
Posts: 21266
138
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Interesting. And rather evil.

Now try it in an XA environment with 2 different databases in a single transaction!

 
Claude Moore
Bartender
Posts: 1200
38
IBM DB2 Netbeans IDE Spring Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Tim Holloway wrote:Interesting. And rather evil.

Now try it in an XA environment with 2 different databases in a single transaction!



Tried. It wasn't so difficult, and works well. Of course you need to define two different entity managers and to setup a JTA coordinator , like Bitronix or Atomikos to enlist both of EM / datasources in a JTA context.
By the way, I was working with an AbstractRoutingDatasource to have a single EntityManager and different datasources agains which to perform operations.
That's a glimpse of hell, at least if you want to have a single global transaction and update / insert items in two distinct database. It's a scenario that rarely occours, but despite this isn't easy at all.
The problem is that an EM is also a cache, and avoids to hit the DBMS as long as it can. If you have nested transactions, the problem that arose sent shivers through my backbone...  
 
We begin by testing your absorbancy by exposing you to this tiny ad:
Java file APIs (DOC, XLS, PDF, and many more)
https://products.aspose.com/total/java
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!