I have 2 projects:
Java EE - with Rest API
Pure Java using Java Scheduler that calls project 1.
In both I would like to use Hibernate.
Since the are using the same database, I would like to share the same Hibernate session
What is the way to do it?
EDITED
I want to use the same Hibernate cache! Not only the classes
Extract the entities, and potentially some common data access classes, in a jar, and use this jar in both applications.
You can use Hibernate Level 2 Cache (likne Ehcache). The L2 cache is responsible for caching records across multiple sessions but only for primary key lookups. If you want queries cache you can't do that with Hibernate when multipel sessions are being used.
You can make your own separate cache implementation (also using EhCache) and have some centralized way of signaling to it when it is dirtied by writes from a certain application.
Related
Our application is a middle-tier application that provides a dozen or so front-end application with access to a couple dozen databases (and other data sources) on the back end.
We decided on using OSGi to separate the unrelated bits of code into separate bundles. This ensures proper code encapsulation and even allows for hot-swapping of specific bundles.
One advantage of this is that any code speaking to a specific database is isolated to a single bundle. It also allows us to simply drop in a new bundle for a new destination, and seamlessly integrates the new code. It also ensures that if a single back-end data source is down, that requests to other data sources are unaffected. One complication is that each of those bundles is loaded by a separate ClassLoader.
We'd like to start using JPA for our new destinations that we're building. Previously, we have been using JDBC directly to send SQL queries and updates.
We've looked into Hibernate 4, but it seems that it was built on the assumption that everything is loaded using a single ClassLoader. Switching between ClassLoaders for different bundles does not appear to be something it can handle consistently.
While it seems that Hibernate 5 may have corrected that issue, all the tutorials/documentation I've found for it gloss over the complexities of configuration. Most simply assume you are using a single application-level configuration file, which will not suit our needs at all.
So, my questions are:
Does Hibernate 5 properly handle connecting to multiple databases, with the configuration/POJos for each database loaded by a different ClassLoader?
How do we configure Hibernate to connect to multiple databases using multiple ClassLoaders?
Is there another JPA framework that might be better suited to our specific needs?
Hibernate is fine but for OSGi usage you also need an intermediary. In the OSGi specs this is defined by the OSGi JPA service spec. It defines how to connect to a JPA provider in OSGi without a hard reference to it.
This spec is implemented by Aries JPA. It also provides additional support for blueprint and declarative services. There is also Aries transaction control service that takes similar approach to supporting JPA and transactions in OSGi it also uses the core of Aries JPA but is a bit different in usage.
The last part you might need is pax-jdbc which allows to define a XA datasource just with configuration. The examples already use it.
To get started easily you can use Apache Karaf which has features for all of the above.
Aries JPA allows to use different databases in the same OSGi application.
Hibernate is an ORM framework which allows developers to handle database from application easily. It also allows multi level caching. Which is a great feature.
I know how does it maintain first level caching.
https://howtodoinjava.com/hibernate/understanding-hibernate-first-level-cache-with-example
My concern is how it maintain first level caching while I have multiple instances of same application related/transact with same database?
My concern is how it maintain first level caching while I have
multiple instances of same application related/transact with same
database?
Each application runs in its JVM, so will have its own Hibernate Session (used for the first level cache) and its own Hibernate second level cache.
Note that in cases of running multiple instances of a same application, you generally wonder how to share the second level cache, not the first level that is specific most of time to the current transaction.
And to get a distributed cache, you have to favor a distributed cache solution as EHCache or HazelCast that can set in front of Hibernate.
There are two projects that talk to the same database (but to different tables) in JPA. One with Hibernate (plus some Spring), one with EclipseLink. Projects have to be merged: one must now call the other.
Both have a persistence.xml configuration, but with vendor-specific flags. Merging both persistence.xml has not been successful as you can imagine. Refactoring one project is out of the question.
I was wondering if one could stop relying on JPA (to avoid the persistence.xml conflict) but still get something with Persistence.createEntityManagerFactory, and have that be compatible with annotated #javax.persistence.Entitys.
No, you cannot (easily) "stop relying on JPA". JPA is an API, that is the list of classes and methods that your application uses to talk to the databases. Not using JPA would mean completely rewriting your database layer, which you presumably want to avoid.
However, you can continue using the two persistence.xmls side by side (possibly merged into one file). To do this, you would maintain two JPA persistence contexts in parallel, meaning you would have two different EntityManagerFactorys in your code for the different parts of your (merged) application.
This will sometimes make life a bit more complicated, because things like Spring integration of JPA usually assume there is only one persistence context, but it should be doable.
While your case seems rather unique, one common reason to have multiple persistence contexts in parallel is when you need to access multiple databases from one application. See for example persistence.xml for multiple persistence units for how this can work.
In principle, this will also work if the two persistence contexts access the same database. You'll just need to be careful with caching in JPA, because that usually assumes noone else is writing to the database. However, if your two persistence contexts never operate on the same table, that should be no problem.
Try using two persistence units in parallel, and if you get stuck, ask a new question :-).
We'd like to use another L2 cache for our big JPA application. We are trying to achieve a shared cache between multiple servers.
We use Eclipselink as JPA implementation, and some legacy codes uses internal Eclipselink API's, so switching is not an option.
Coherence/Toplink Grid seems too expensive (4000$/cpu?).
Is there a way we could plug another cache implementation? Is something specified in JPA 2 (I can't find anything in the specs, but maybe I just misread it)? Proprietary (=Eclipselink specific) solutions are ok, as long as they are somewhat documented or simple enough (we don't want that to break).
Is there a way we could plug another cache implementation?
Did you investigate the use of the EclipseLink shared object cache that comes with EclipseLink? Going by the description, the shared object cache is not confined to a single EntityManager alone, and is available across the lifecycles of several Entity managers, i.e. across several transactions. It is of course, constrained to the lifecycle of an EntityManagerFactory, which may be as live as long as the application is running in the container.
The EclipseLink shared object cache is different from Oracle Coherence, and I believe it is not licensed and packaged separately, thereby making it available on all containers.
JPA does not specify a pluggable cache interface. I don't know if it ever will, but if it does, my bet is that it won't be until after the resurrected JSR-107 finishes defining a standard API to object caches, which JPA would then be able to use. It might also have to wait for JSR 347, which is defining another cache interface, whose relationship to JCache is somewhat unclear (there is open factional warfare between and within the groups, with some members of the 107 expert group trying to declare 347 an independent republic, and invade Mexico).
So, until then, you're at the mercy of your provider's cache interface. I am not an EclipseLink expert, but last time i looked, i couldn't see a pluggable second-level cache interface. In fact, i think only Hibernate and, of course, DataNucleus, have them.
Most cache implementations are not distributed (other than Coherence), just local.
EclipseLink already supports a share cache and cache coordination for caching in a cluster.
What cache do you intent to use, and what benefit do you intend to get from it?
EclipseLink does support integration with 3rd party caches, this API was created for the Coherence integration, although Coherence is the only cache that currently provides an integration.
I'm using JPA and I am using second-level cache for all the reference entities.
Everything's working well, I can get the entities from second-level cache is they were already been selected before.
Now, I have two applications, they both use the same database (so they both use the same table, values, etc).
1.The read-only application just read data from database, it doesn't modify the database at all. Therefore, I choose the "READ_ ONLY" concurrency strategy for the second-level cache, aiming at a better performance.
2.The read-write application read and write as well the data of database, it modify the database. Consequently, I have to choose the "READ_ WRITE" or "NONSTRICT_ READ_ WRITE" concurrency strategy for the second-level cache.
However, the concurrency strategy is assigned in the annotation of each entity class, so I cannot change it programatically. (I don't use class mapping files for JPA, so I can't use two mapping files, each for a different concurrency strategy for the same entity class.)
My Question is, is there a good way to change the concurrenty strategy of the second-level cache on the fly according to my 2 different applications?
I have not used Hibernate, but at least if you use JPA it is possible to override even a single annotation with a deployment descriptor file. You should also be able to override also any vendor specific property with the deployment descriptor.
Unfortunately I cannot give you an example but hope this helps you.
So Therefore, I think the current solution is to replace all the annotations of each entities with Hibernate mapping files, so that for different deployment (application as well), we could use different Hibernate mapping files.