I know there are quite a few questions on my topics already, but I haven't really been completely satisfied with any of the answers. It's also difficult to find decent information on the web, so I'm starting a new question.
Basically, I'm struggling with how to best use JPA in a Spring application for a scenario that must comply to the following requirements:
Using Spring Transaction management
Using multiple Persistence Units (with Spring Data Repository support)
Using multiple DataSources (I want to be able to switch the DataSource for a PersistenceUnit dynamically at runtime)
Combining parts of the application (that include JPA entities) in separate modules to use them in different projects
Consider the following UseCase
Application A allows the User to read and write DB data from different DataSources, D1, D2, Dn. I only need a single PersistenceUnit P1 to define the needed entities
Module M contains two entities AuthUser and AuthRole that are used to store user and permission information. I'd like to use it modularly in different projects. Basically, I need to be able to define the PersistenceUnit P2 that only contains the two entities and a DataSource Da as the users are stored in ONE database, independent from the other DataSources D1, D2, ... the application accesses.
Application A includes Module M and defines which DataSource it should use
The issues i ran into:
I would like to use #PersistenceContext and #Transactional in Module M, without having to specify explicit persistenceUnits or transactionManagers everywhere. Ideally, Spring would use the PersistenceContext / EntityManager of a running Transaction. This way, I would specify the desired PersistenceUnit in a transactional method of Application A and Module M would inherit the transaction and PersistenceContext. I couldn't find a solution of how to do this. I was thinking of providing a custom PersistenceAnnotationBeanPostProcessor, but I couldn't find any resources on the web on this subject.
To use multiple DataSources with the same PersistenceUnit, I looked into AbstractRoutingDatatSource. This should work, even though I'm suspisous on how it will cooperate with the Transactional annotation. Any experience on using it and on how to prevent changing DataSources in the middle of a transaction?
I hope I could make my point clear. I didn't want to include too much code as in a first instance, I'm interested more in the conceptual answer than the technical one. To boil it down to one (large) sentence:
What's the best practice in Spring / JPA to build modular, transactional applications using multiple PersistenceUnits and DataSources without having to specify hard coded persistence information (like persistenceUnit names) in the source code (especially of the modules)?
Related
I'm working on a new project, using concepts like clean architecture, protecting my model and business rules from external dependencies and frameworks. Also, I prefer not to use traditional ORM libraries (like JPA/Hibernate) and have choose to use plain jdbc (through spring jdbctemplate).
It was going pretty well, but I'm getting tired of write 20x almost the same query for all my domain classes on a basic crud reposity. So, I take a look at Spring Data JDBC, but it appears that it's necessary to add annotations on my domain classes to make it work properly. I really don't want to do that, first because I want to make my domain cleaner as possible from any dependencies, and second because this is one of the (many) things I really dislike on JPA.
I was wondering that, the repository needs only 2 things: a rowmapper definition and the PK definition (and both could be defined at the repository itself) avoiding the complete use of annotations.
So, my question is there any way to use Spring Data JDBC without annotations?
No, there is no easy way to use Spring Data JDBC (https://spring.io/projects/spring-data-jdbc).
What you could do is to replace those classes that do the annotation interpretation (RelationalPersistentEntityImpl, and BasicRelationalPersistentProperty) and replace them with something that gets the information from elsewhere.
There is a different framework wich might fit the bill which is also named Spring Data JDBC 🤷♀️ https://github.com/nurkiewicz/spring-data-jdbc-repository
It seems pretty close to what you are looking for but it has its last commit 6 years ago and is archived on Github.
I have a module with a persistence.xml for several classes. I have an application which uses that module, but wants to augment that EntityManagerFactory with a couple of other classes that are specific to this application and don't belong in the module.
If I create a persistence.xml in the application that overrides the persistence unit it does not work reliably (it does work when run from IntelliJ's debugger, but does not work when invoked using a maven appassemble package) because it seems the rules governing which of the persistence.xml files in the various jars takes effect are beyond my understanding, and probably difficult to control.
If I create a second persistence unit to contain only the new tables, then I will need multiple EntityManagerFactory-s to retrieve the various object types in JPA. I do not currently need to execute queries that join objects from the library module with objects specific to the application module, but I am reasonably certain it would be impossible if the objects were in different persistence units.
Even worse, using multiple persistence units appears to make derby angry because the second persistence unit fails when it finds that the database is already opened (by the first persistence unit; why derby can't share in the same JVM I don't know, and there may be workarounds I do not know).
What are the dangers if you have persistence units that overlap? ( both units have objects mapped to the same table in the same database )
What are the proper guidelines for dealing with persistence units from multiple .jars ?
Using standard JPA functionality, there is no means to supply additional entity classes in runtime.
The approach I recommend is to remove persistence.xml from your modules and create orm files, which contain the same entities as original persistence.xml files.
Then create single persistence unit in the application and include orm files from all required modules.
This is what has always worked for me an it seems the only reasonable approach with current JPA version.
This way, you end up with single persistence unit, and still having modular and extensible sets of entities.
For a few days, I have been researching JPA and Hibernate.
Now I got confused about JPA - Hibernate interactions.
I know JPA is a specifcation and Hibernate implements it. But the missing point is a working principles . I mean in a real application, what does hibernate do and what does jpa do ? I am trying to get below questions. Let me ask you;
Question 1 : Is JPA only abstract notion ? Does it consist of only interfaces? (I have observed that everyting is interafce in
javax.persistance package.)
Question 2 : Is JPA enough to perform CRUD operations ? (Is it possible to use JPA without Hibernate or etc.) If it does , why we need JPA providers such as Hibernate or etc. ?
Question 3 : And last one , I am searching for concrete something. I
need to know Database->JPA->Hibernate interaction. For
example while Saving and fetching something , What does happen in
background ?which one is performing database operations(hibernate or jpa) or which one is responsible for providing db connection ?
I mean, in jpa/hibernate based application , who is responsible for what?
Question 1:
Yes, exactly! JPA is just a specification as you already know. It only says what can be done but doesn't say how it should be done or doesn't implement any behaviour. You can use JPA annotations with javax.persistence classes but in the end when you run your application nothing will happen!
Question 2:
As I said above, JPA is just a blueprint saying what can be done. Hibernate, OpenJPA, Toplink etc. actually implement that specification. They perform the operations differently so there might be tradeoffs in speed etc. but all of them have to be able to perform the same set of operations specified by JPA. Some might give you more features but never less.
Question 3:
Again JPA isn't performing any actions, it just specifies what can be done. How it's done, how the code <-> db interaction is performed, what kind of SQL queries are created it's all implementation specific and will differ (for instance Hibernate might create different SQL queries for the same thing than OpenJPA). How your DB interactions are performed in the end is determined during runtime by the implementation (Hibernate). You can try to find it all in the documentations for the concrete implementation. You can also print the SQLs that are performed for instance.
You might ask "then why do I need JPA"? Well that's because you can (in theory!) change the implementation just by changing the jar on the classpath to a different library (i.e. from Hibernate to Toplink). In practice sometimes it's not that easy due to implementation specific features or how each implementation handles SQL queries, tables etc.
As you state JPA is just a specification, so there is no implementation but every Java EE container should support it ( implementation of JPA is included in application server ).
JPA implementations in Popular application servers :
Glassfish - EclipseLink (reference implementation)
JBoss - Hibernate
Websphere - JPA for WebSphere Application Server persistence, Apache OpenJPA
So when you are using application server you can use JPA interface to perform any CRUD operation through particular JPA implementation.
Tomcat does not support JPA out-of-the-box. You can use JPA in applications deployed on Tomcat only if these applications embed some JPA implementation. Or use Apache TomEE project which provide JavaEE features for Tomcat.
Remember that Hibernate has JPA implementation but also more addictional (cool) features. But if you are using only elements from JPA spec you can anytime easily switch to another JPA implementation.
As you mentioned yourself: JPA is a specification, Hibernate an implementation!
1: Yes, correct this is the technical part of the specification in form of Java Interfaces.
2: NO, JPA is not "enough", JPA can't do anything, it is just a specification.
3: An Interaction exists only between Hibernate and the Database (actually, there are other parts like the database driver involved, but don't mind...).
The idea behind this separation is you can write code that only uses the interfaces from javax.persistence. At one single place you (or maybe a container like an application server) define which implementation you want to use. This makes your application very portable, and you could choose to switch implementations as you like (theoretically, in practice it is never that easy...)
Being completely new to Enterprise Java development and after reading the following tutorial.I managed to develop my first session bean. After reading a little about session beans I do have some questions about it (session bean) and I hope the experts out here could help me out.
Normally in a servlet scenario without using EJB we would do something like the following to accomplish a certain task
StudentList stud = businesslayer.businessMethod_GetStudentsFromDb();
Now the businesslayer would call the service layer which would get the details from the DB and return it.
Now my questions are as follows:
1-If I were to implement this mechanism using say a stateless EJB will I have to copy the domain package which contains the domain object StudentList to the "-ejb" folder of my enterprise project (I am using netbeans).Similarly will I have to copy other Business methods from the source folder of my "-war" folder to the ejb folder just so that the stateless bean in the "-ejb" folder can use those methods. Cant classes inside the "-ejb" folder use classes insider the source folder of the "-war" folder.
2-This is the question so far i could not understand. What advantage would i get if i used EJBs instead of my current mechanism ?
1
If you're building a single application, there's nothing you need to copy. If you want to have a very strict separation between business code and web/view code you can create an ear, with an ejb module and a web module. All classes in the web module can access all classes in ejb module, but the reverse is not true. This effectively imposes a layering in your application.
But you don't have to go for this separation. You can also just put your EJB beans in a single war together with your Servlets and what have you. There's no restriction on where you put your beans. It can be in a separate package, or in the same package as your Servlets.
You might wanna look at this example I made: http://arjan-tijms.omnifaces.org/2011/08/minimal-3-tier-java-ee-app-without-any.html. There, BusinessBean is an EJB that resides in the same (default) package as the JSF backing bean in a single war.
In the single war setup, everything can access everything. Do note that even in this situation you probably would like to keep your business code "clean" and keep things like HttpRequest and such out of it.
2
EJB beans, especially EJB light, provide exactly those things that most every web application needs: transactions, pooling, thread-safeness, security and injection. You'll get the most out of EJB beans when combined with JPA. The advantage is that your code will be much less verbose and at the same time shielded from race conditions and inconsistencies that you'll run into when using plain JDBC.
E.g.
#Stateless
public class CustomerService {
#PersistenceContext
private EntityManager entityManager;
public void addCustomer(Customer customer) {
entityManager.persist(customer);
}
}
Without EJB you'll need a bunch of try/finally blocks which open and close the connection, start and commit the transaction etc. And without JPA you'll have a large block of tedious code that inserts individual fields of the Customer entity shown in the example into a prepared statement.
If you (later) have services that call one or more other services and either everything needs to be saved to the DB or nothing (as opposed to something undefined in between), then this is quite a challenge to accomplish in plain JDBC. You'll have to pass open connections around and need special variants of each service method that opens/closes connections and starts/commits transactions in addition to methods that can be used in an intermediate phase. Before long, this will become highly complex and a big ball of mud.
With EJB, every method in an EJB bean that you call from within an other EJB bean automatically joins the ongoing transaction or starts its own if no transaction is in progress. This alone massively simplifies many common business tasks carried out by typical web applications.
Don't let anyone tell you that only "enterprise applications" need transactions, and web applications don't need this. This is simply not true. A transaction is a very basic thing when doing DB operations, at the same level of basic requirements as primary keys or foreign keys are. When performing business logic for say an order (in a webshop), you definitely don't want your inventory being decremented, but no actual order being send, or an order being send but no money subtracted from your customer's account, etc etc. The simplest of business logic often involves writing to at least two tables, and every time that happens you'd better be using transactions.
Do make sure you're using EJB 3 though. Stay far away from everything that has to do with EJB 2. Don't even touch things like home interfaces or Entity Beans, which have been deprecated for some 6 years now. (don't confuse EJB Entity Beans with JPA Entities though, despite the unfortunate name similarity these are completely different. JPA Entities are very sane and useful)
I want to create a modular(plugin-like) application that uses JPA as its persistence abstraction, and this application should be extensible by third parties.
The catch is that I want this application and its plugins to be easily portable to other databases/JPA providers, so the third party vendors can't know anything about the used JPA provider(or databases connections), they can only extend the persistence layer by defining new entities to be stored in the main app persistence unit(this would allow one to switch databases without having to reconfigure every module to point to the new db).
Can I do something like that with JPA? I can do it easily with .NET's nHibernate(and probably with Hibernate) but I prefer to program against JPA since I'm in a Java EE environment.
Funnily, I have made exactly this using OSGi, Equinox and EclipseLink, but it's not trivial. Essentially, a custom bundle takes all persistence.xml files from all resolved bundles, merges them into a single persistence.xml that is used to initialize the EclipseLink Persistence Provider. Additionally, there are some custom hooks that allow me to specify f.e. connection options separately for development and deployment.
Drawbacks: say bye-bye to container-managed persistence, but it's still possible to join transactions. Also, some tools react violently to cross-bundle entity references. Also, if you add a new bundle with new entities, you will need to have set up the database with the proper tables, references, indexes & constraints beforehand.
Advantages: Drop in new bundle, see it work at once, dynamically, without restarting the container.
I am also researching how to do JPA in a modular way (in the Netbeans module system or in an OSGI container).
One thing you should be aware of is that if you need to build a central, big EntityManagerFactory (by the central persistence module) than you may have some issues if your application is big:
If the persistence module needs to react to module startup/shutdown events, it needs to rebuild the central EntityManagerFactory when a module is added or removed. If the application is big (lots of classes), rebuilding the EntityManagerFactory is slow and costly.
The application needs not storing references to the EntityManagerFactory because if a module is added/removed the old one becomes stale. The application should work with very short-lived EntityManager and always get the EntityManagerFactory.
It may be more flexible to build EntityManagerFactories for every JPA-using module, but that may need more memory and may take up more computing power until all of the EntityManagerFactories are created for every module (although EntityManager factories may be created on-demand by your central JPA service).
Dynamic-JPA (http://www.dynamicjava.org/projects/dynamic-jpa) may help if you work in an OSGI container.