I'm creating a Java EE application that's using JPA for data access. Initially I used EclipseLink, but the bundled Geronimo Javamail implementation that it depends on via Moxy was giving me some odd issues and I couldn't force it to use Sun Javamail, so I've switched to Hiberate as the JPA provider.
EclipseLink was ignoring the lazy/eager annotations, it was eagerly loading everything. Hibernate pays attention to those annotations, and so dependant objects aren't loaded. That means if I load say a person, with a lazy loading of the persons parents, if I access the parents in the view it's not lazy loaded, I get an exception that says the database session's closed.
I understand there are two ways to get around this:
- Open Session in View pattern/antipattern (which isn't great from a layered point of view, and can have the N+1 database calls problem, but is easy)
- Have service methods that load all the data the view needs (which makes the service layer messy with lots of duplicate methods to get varying amounts of data)
For reference my layers are View -> Controller -> Service -> Entity Object -> JPA. I don't have a dto as it's a small app and I don't like the DTO anti-pattern.
Thinking about the Open Session in View pattern, the problem is the OpenSessionInViewInterceptor and OpenSessionInViewFilter are both Hibernate specific, and both require you to declare a hiberate session on your Spring configuration files. I prefer to stay with pure JPA, configured with a persistence.xml file.
What are my options here? Can I just change my Spring configuration to load Hibernate explicitly, but then use pure JPA inside my application? Is there a pure JPA way achieve the same result, lazy loading from the view?
it sounds odd the EclipseLink ignores standard JPA annotations.
the javamail implementation should not be in any way related to JPA
there is OpenEntityManagerInViewX (filter/interceptor) which handle the same scenario for JPA
you can easily go without this pattern if you declare and use your collections wisely.
Related
I am currently creating a J2EE application and there is a part of it that is running outside the container, using a ServletContextListener to launch it.
However I also need to access the database from this part.
I currently have an Entity and a Stateless Session bean to fetch use the EntityManager.
I tested multiple things ( EntityManagerFactory, Initial Context, EJBContainer ) but I didn't manage to make any of them work.
How do I need to do it ?
You do not need EJB, actually you cannot create Ejbs outside the container. You need JPA, an OR-mapper and JDBC.
These normally are correctly configured in your EJB-Container. Outside the container you have to do that yourself.
You have to define your dependencies right, so that the correct JDBC-Driver is available and the OR-Mapper (probably eclipselink or hibernate?)
After that, you need define a presistence.xml to define the Entities to be used and to define how the DBMS is accessed via JDBC.
If that all is correctly configured EntityManagerFactory is the correct way to create an EntityManger for the persistence-unit defined in persistence.xml.
There are many examples available on the net. e.g.:
https://examples.javacodegeeks.com/enterprise-java/jpa/java-persistence-xml-example/
should work, if you are using eclipselink.
https://docs.jboss.org/hibernate/orm/3.6/quickstart/en-US/html/hibernate-gsg-tutorial-jpa.html
in case of Hibernate.
JPA specification defines two ways of how to configure and use it:
Application-managed Persistence Context
Container-managed Persistence Context
With the Application-managed Persistence Context approach, the application code directly creates EntityManager using EntityManagerFactory. With the Container-managed Persistence Context, the container is responsible for this.
Seems this is all related only to controlling of EntityManager instances (create, destroy, etc).
The question is. Why do we have two different methods in the PersistenceProvider class? (I mean with different parameters)
I mean these:
public EntityManagerFactory createEntityManagerFactory(String emName, Map map)
public EntityManagerFactory createContainerEntityManagerFactory(PersistenceUnitInfo info, Map map)
The first one seems for the Application managed type. And it works only with the persistence.xml file because it can take only the name of the persistence unit. The second is for Container managed type. And it can take the PersistenceUnitInfo object. Why I cannot use the Application Managed type with the custom PersistenceUnitInfo parameter? It seems both variants work with containers anyway. The difference occurs only in controlling EntityManager instances. When we are talking about the configuration of EntityManagerFactory, this object always resides inside a container, because I can inject it with the #PersistenceUnit annotation.
This seems strange, as I still can specify the data source for the Application managed type with the <jta-data-source> tag. And I can do the same with Container managed type using the java setter method. If I can do the same things, why I am limited with only XML tag in one variant and I can use java setter (java configuration) in the second?
MOST TYPICAL JPA CASES
So the "container" here in this terminology refers to a Java EE / Jakarta EE container (aka an "application server"). I think the reason this probably seems so confusing is because most documentation is geared towards the typical application developer, but you're asking about code that's typically the responsibility of the JPA provider and the container provider.
In the most typical cases, an application running in a Java EE / Jakarta EE container would not use these PersistenceProvider methods. It might inject an EntityManager (container-managed persistence context) or inject an EntityManagerFactory (app-managed persistence context).
The PersistenceProvider#createContainerEntityManagerFactory(PersistenceUnitInfo info, Map map) method is intended for a JPA provider to allow a Java EE / Jakarta EE Container to create an EMF which can probably be used for both container-managed and application-managed persistence contexts.
And in a Java SE environment, the application would call Persistence.createEntityManagerFactory(...) which would find a Provider and call its PersistenceProvider#createEntityManagerFactory method. Here too, the app wouldn't need to call PersistenceProvider itself.
So if you have a typical app and you're trying to figure out what PersistenceProvider method to call, then you probably are on the wrong track and should be starting from a better example.
SPECIAL CASES
This all works well and is handled for you, as described, when you're using the typical aproach of using the persistence.xml to load the persistence context. If your application wants to do something different and custom, however, then you get into the realm of maybe wanting to call the PersistenceProvider yourself. E.g. this is one article that discusses the subject a bit. You may end up tying your application to a specific provider with this approach.
I'm not sure exactly what the specification says about this case, if anything. I would describe it as having more of an "app-managed persistence" feel since you're certainly creating EntityManager(s) yourself but I'm not sure if that's a correct or helpful description.
Is it possible to use hibernate-search only for it's annotations (bean => document/document => bean mapping), without using a database at all? If so, are there any online samples that show basically how to set this up?
I found the following: http://mojodna.net/2006/10/02/searchable-annotation-driven-indexing-and-searching-with-lucene.html, but I'd prefer hibernate-search if it supports my use case.
Hibernate search 3.4 has decoupled the query engine from Hibernate Core. For instance, Hibernate Search is reused to implement queries with Infinispan. I don't know if the code is packaged so that you could use HS with, let's say Spring and JDBCTemplate (something I would like to do). That's a lead I will investigate later but maybe you can check it out...
Starman is correct, Hibernate Search in version 3.4 is abstracting the search engine from Hibernate Core, and the Infinispan Query is an integration example which works fine without a database. There would be no problems with Spring either, but you'd need to make sure to send update event to the query engine so that the index doesn't get out of synch. When using Hibernate the advantage is that it transparently listens for changes to the database and applies them to the index at transaction commit, so the index is always in synch (or close, if configuring Search to use async backends).
I'd suggest to look into the code of Infinispan Query, as it's very small and just delegating calls to expose an Infinispan flavoured API. Most of the code is tests or integration to properly manage the lifecycle of the engine: start and stop it together with Infinispan.
I don't think that's possible because when you enable Hibernate search you are enabling that on a Entity and that Entity has references to the table and the search index.
I want to share some domain objects between my client and server apps.
Starting with Hibernate 4, the Hibernate annotations were integrated in hibernate-core (used to be a separate jar), see http://in.relation.to/Bloggers/NoMoreHibernateannotationsModule
I would really prefer to stick with annotations (and not switch to xml based mapping).
At the same time I would really like to avoid bundling the hibernate core dependencies with the client (which will be transferred to the user via http through java web start, ideally on every startup).
Do I have to go back to Hibernate 3.x? Are these annotation dependencies needed to run the client or do I just need them to compile the client?
Thanks
You don't need to have the annotations of a class in the classpath to be able to load a class.
That said, a Hibernate entity contains collections and references to other entities. The collections are instances of Hibernate collections, and the references can be Hibernate proxies, if they're lazy-loaded. So if you serialize a Hibernate entity from the server to the client, the client will need the Hibernate jar(s) in its classpath to be able to load them.
If you want to avoid the Hibernate dependency at client-side, you should consider transferring DTOs to the client rather than Hibernate entities.
I am currently having a problem with understanding a concept of JPA.
I am currently using/developing recent EclipseLink, Glassfish, Derby database to demonstrate a project.
Before I develop something in much bigger picture, I need to be absolutely sure of how this PersistingUnit work in terms of different scopes.
I have bunch of servlets 3.0 and currently saving user's associated entity classes in the request.session object (everything in the same war file). I am currently using Application-managed EntityManager using EntityManagerFactory and UserTransaction injection. It works smooth when it is tested by myself. The different versions of entities occur when 2 people accessing the same entities at the same time. I want to work with managed beans cross the same WAR, same persistence unit if possible.
I have read http://docs.oracle.com/javaee/6/tutorial/doc/bnbqw.html and bunch of explanations of those scopes which don't make sense at all for me.
Long story short, what are the usage and difference of app and container managed EntityManagers?
When you say application managed transaction it means its your code which is supposed to handle the transaction. In a nutshell it means:
You call:
entityManager.getTransaction().begin(); //to start a transaction
then if success you will ensure to call
entityManager.getTranasaction().commit(); //to commit changes to database
or in case of failure you will make sure to call:
entityManager.getTransaction().rollBack();
Now imagine you have a container, which knows when to call begin(), commit() or rollback(), thats container managed transaction. Someone taking care of transaction on your behalf.
You just need to specify that.
Container managed transaction(CMT) could be regarded as a kind of declarative transaction, in which case, transaction management is delegated to container (normally EJB container), and much development work could be simplified.
If we are in a Java EE environment with an EJB container, we could use CMT directly.
If we are in a Java SE environment, or a Java EE environment without an EJB container, we could still take advantage of CMT, one way is to use Spring, which uses AOP to implement declarative transaction management; Another way is to use Guice, which uses a PersistFilter to implement declarative transaction.
In CMT, a container (whatever an EJB container, Spring or Guice) will take care of the transaction propagation and commit/rollback stuff;
Application managed transaction (AMT) differs from CMT in that we need to handle transactions programmatically in our code.