JPA / Hibernate question ( #PrePersist, Session API clarification) - java

I am working currently on creation of some tests on my app.
I have faced an issue which needs to involve #PrePersist feature from JPA.
Unfortunately those interceptors aren't fired, while persisting, updating ( etc ) and I found that with Session API of Hibernate this feature does not work. Here appears my question.
What is the main prove that Session API is used in the app, and is there a chance to retrieve directly EntityManager so the triggers are fired ?
I greatly appreciate any hints and advice on this topic,

What is the main prove that Session API is used in the app
Oversimplifying, the EntityManager API is a "shell" around the original Session API. But I think you want another answer :-) The only other answer I can give is to check the source code. Or, if you don't have the source code, you'll want to change the logging configuration. Set it to "trace" for the Session class, then you can see exactly when it's being called.
and is there a chance to retrieve directly EntityManager so the triggers are fired ?
Sure, depending on the application server or framework you are using. If you have a "real" application server, you can retrieve the EM from it. If you are using a standalone application, you can use the EntityManagerFactory to create a EntityManager. But before doing that, I would check the examples in the Hibernate test suite:
https://github.com/hibernate/hibernate-core/blob/master/hibernate-entitymanager/src/test/java/org/hibernate/ejb/test/LastUpdateListener.java
Also, if you are not using the JPA API, you can still have event listeners in Hibernate:
http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html_single/#objectstate-events

Related

Design Principal for JPA EntityManger

I am using JPA in a web application running in Tomcat 8. I am relatively new to JPA, and am having a hard time figuring out how to properly design my web app to use EntityManager. I have read "Java Persistence with Hibernate" and "Pro JPA 2", as well as a few posts about Entity Managers, but I am still unclear as to how to properly design my web app.
Should I create a singleton EntityManager that is used by the web app to service all requests, such as to CRUD (create, read, update, delete) entities?
Or should I ask the EntityManagerFactory to create a new EntityManager for each user request that comes in and close the EntityManager when I'm done processing the request?
I'm currently doing development on my local machine, where I am the only user.
What are the pros/cons of each approach?
Do both scale to hundreds of users?
I don't have the real world experience to answer these questions, so I'm looking for some answers/guidance from people who've used JPA in enterprise business apps.
Thanks
I have created ScopedEntityManager wrapper to ease JPA use in a servlet webapp. It creates an auto managed EM for the http request using a threadlocal variable.
It makes sure EM is rollbacked+closed after a servlet request. Same EM is returned in a getter method for the same request thread. You just need to commit() if all is good. Throwing an exception is not a problem because the request listener take care of the rollback().
See this how to instantiate a EM wrapper and life cycle manager.
https://github.com/Murmur/ScopedEntityManager/blob/master/src/es/claro/persistence/ScopedContextListener.java
https://github.com/Murmur/ScopedEntityManager
https://github.com/Murmur/ScopedEntityManager/blob/master/example_webapp/webapp/jpa1.jsp
So yes create a new EntityManager for each http request.

How do I properly set up cross-store persistence using Spring Data JPA + Neo4j?

I am trying to get a very minimal JPA + SDN (Spring Data Neo4j) cross store project running and am trying to demonstrate that saving a partial entity using a JPA repository call will create a corresponding node in Neo4j.
I have followed the instructions / advice that I have been able to find on SO, Google and Spring's site but am currently still having trouble standing things up. I currently have a minimal test project created at:
https://github.com/simon-lam/sdn-cross-store-poc
The project uses Spring Boot and has a simple domain containing a graph entity, GraphNodeEntity.java, and a partial entity, PartialEntity.java. I have written a very basic test, PartialEntityRepositoryTest.java, to do a save on the partial entity and am seeing:
The wrong transaction manager seems to be used because the CrossStoreNeo4jConfiguration class does not properly autowire entityManagerFactory, it is null
As a result of the above ^, no ID is assigned to my entity
I do not see any SDN activity in the logs at all
Am I doing something glaringly wrong?
More generally, I was hoping to confirm some assumptions and better understand cross store persistence support in general:
To enable it, do I need to enable advanced mapping?
As part of enabling advanced mapping, I need to set up AspectJ; does this include enabling load time weaving? If so is this accomplished through using the #EnableLoadTimeWeaving config?
Assuming that all my configuration is eventually fixed, should I expect to see partial nodes persist in Neo4j when I persist them using a JPA repository? This should be handled by the cross store support which is driven by aspects right?
Thank you for any help that can be offered!
I sent a message to the Neo4j Google Group and got some feedback from Michael Hunger so I'm going to share here:
Turns out the cross store lib has been dormant for a while
JPA repos are not supported, only the EntityManager operations are
The cross store setup was not meant for a remote server and was not tested
So in summary my core understanding / assumptions were off!
Source: https://groups.google.com/forum/#!topic/neo4j/FGI8692AVJQ

Spring Roo JPA - Why are manual DB updates automatically available in Persistence Context?

I have developed a web app using Spring Roo (Spring MVC 3), JPA 1, Hibernate, JSTL, JQUERY etc..Persistence Contexts are application managed via a JPA Transaction manager. DB used is MSSQL2005. The application is running on JBOSS 5.
Everything works fine. My question is something that has been on my mind, yet i have yet to come across a suitable answer.
Suppose the following:
I retrieve some row from Table T using entitymanager.find(), and present the data to a page
I manually change one of the field values in the row (via SQL an gui tool).
I immediately repeat step (1), and I have the manually updated value available.
Is this correct? My understanding was that values within the persistence context do not get updated unless:
calling em.refesh()
object is not available in PERSISTENCE CONTEXT (--> query DB instead)
My experience seems to contradict the link below, which actually makes logical sense to me.
Updated data (in Database) is not visible via JPA/Eclipselink
Many thanks
NaP
This is the correct behavior. The values within a persistence context won't be updated unless you call em.refresh() within a SESSION.
When you retrieve the web page again, the old session is closed and a new session is opened with new data reflected.

Multi-user Datasources - Spring + Hibernate

I'm writing a web app that supports multiple users. Each user has their own database - using H2. all database schemas are the same.
I wish to use Spring + Hibernate for this application.
So I'm stuck at how to associate a user's database with that user - maybe associated it in the HTTPSession, and extend spring's AbstractRoutingDataSource? but wouldn't this effect Hibernate's cache? Another way is to have a SessionFactory with each datasource, even though every datasource's schema is the same... so I see that as a waste.
Anyways selecting the datasource needs to be dynamic - they can't be pre-configured in context files, as each new user will have its own database created. Is there any existing frameworks/solutions?
I don't know too much about Hibernate Shards, maybe that works?
I might be wrong about the (strict) need to have one SessionFactory per database, as suggested by some resources:
Dynamic DataSource Routing
I'll take some time to re-read everything tomorrow (I didn't get all the details to be honest) and to fully understand the implications of such a setup (although it seems clear that it will break the second-level cache). I'll come back on this later.
I'm writing a web app that supports multiple users. Each user has their own database - using H2. all database schemas are the same.
I wonder how this will scale... How many users do you have? How do you run H2, what mode?
So I'm stuck at how to associate a user's database with that user - maybe associated it in the HTTPSession, and extend spring's AbstractRoutingDataSource?
You'll have to build a SessionFactory per user and associate it to the logged user (in a Map, using the login as key) and then obtain a Session from a given SessionFactory. Binding the lifecycle of the SessionFactory to the HTTP session seems to be a good idea (to save some memory) but I am not sure Spring will be very helpful here. I might be wrong but a variation of the HibernateUtil class and a fully programmatic approach looks easier. I'm not sure you'll need multiple connections per user by the way.
but wouldn't this effect Hibernate's cache?
What cache?
Another way is to have a SessionFactory with each datasource, even though every datasource's schema is the same... so I see that as a waste.
Oh, it's a waste, but that's what you want to do (one database per user). And you don't have the choice (you need one SessionFactory per datadabase). Why do you need one database per user actually? Are you sure this is a wise decision? As already hinted, this means much troubles, won't scale well, adds complexity, etc. Why not using a single database and associating data to the user?
Anyways selecting the datasource needs to be dynamic - they can't be pre-configured in context files, as each new user will have its own database created. Is there any existing frameworks/solutions?
Not to my knowledge. Which is also why I think you'll have to do everything programatically.
I don't know too much about Hibernate Shards, maybe that works?
Given the dynamic needs of your application, I don't see how it could help.
This may help you:
Dynamic Datasource via Spring using HotSwappableTargetSource
Hibernate + Spring using multiple datasources?
Thanks to the help from the 2 people (Pascal and org.life.java)!
It is possible, but with some problems: e.g. the hibernate 2nd level cache/query cache.
This link supplied by Pascal is a very good resource:
http://www.jroller.com/kenwdelong/entry/horizontal_database_partitioning_with_spring.
My main motivation for giving each user a separate database is because the data is likely to grow rapidly, thus horizontal partitioning is required.

What is the cause of EJB 2.x "reentrant method call detected" Exceptions? How to solve them?

I'm mantaining a EJB 2 CMP legacy app runing on a JBoss 4.0.4 GA application server with deployed entity/stateless session beans. All the EJB boilerplate code is generated via XDoclet from the EntityEJB/EntityEJBManager annotations.
I've noticed that when my GUI client invokes the facade create method, I have lots of cases of EJBException in my server log with the "Reentrant method call detected" message, which rollbacks the transaction.
What does this Exception means? How can I avoid having such error (which unfortunately, I wasn't able to reproduce yet)
Update: Found this link that explains what is meant by reentrancy, however, seems to me that it says my app cannot be accesed concurrently?
I've seen this before where EJB1 calls EJB2 which calls back to EJB1 within the container as part of the same transaction.
You can tell the container to allow this by marking EJB1 as reentrant which will allow it to be accessed multiple times in the same transaction.
This is done in the deployment descriptor with the following tag:
<reentrant>True</reentrant>
There should be a corresponding EntityEJB annotation that XDoclet can use to generate this for you.
we just came across the same problem and our solution was two-fold. Firstly we ensure that none of ejb's had transaction attributes of NotSupported within our ejb-jar.xml. We then used "instance per transaction" as our optimistic locking strategy. It's a bit of a belt-and-braces approach, but it works
It does mean that the Entity bean in question cannot be accessed concurrently, which makes sense since it would likely corrupt the data.

Categories