What is the difference between:
#Autowired
private EntityManager em;
versus:
#PersistenceContext
private EntityManager em;
Both options work in my application, but can I break something by using the #Autowired annotation?
You shouldn't use #Autowired.
#PersistenceContext takes care to create a unique EntityManager for every thread. In a production application you can have multiple clients calling your application in the same time. For each call, the application creates a thread. Each thread should use its own EntityManager. Imagine what would happen if they share the same EntityManager: different users would access the same entities.
usually the EntityManager or Session are bound to the thread (implemented as a ThreadLocal variable).
Source: https://stackoverflow.com/a/42074452/2623162
EntityManager instances are not thread-safe.
Source: https://docs.oracle.com/cd/E19798-01/821-1841/bnbqy/index.html
Please notice that #PersistenceContext annotation comes from javax.persistence package, not from spring framework. In JavaEE it is used by the JavaEE container (aka the application server) to inject the EntityManager. Spring borrowed the PersistenceContext annotation to do the same: to inject an application-managed (= not container-managed) EntityManager bean per thread, exactly as the JavaEE container does.
#PersistenceContext allows you to specify which persistence unit you want to use. Your project might have multiple data sources connected to different DBs and #PersistenceContext allows you to say which one you want to operate on
check the explanation here:
http://www.coderanch.com/t/481448/java-EJB-SCBCD/certification/unitName-PersistenceContext
#PersistenceContext:
does not return entity manager instance
it returns container-managed proxy that acquires and releases presistence context on behalf of the application code
#PersistenceContext is a JPA standard annotation designed for that specific purpose. Whereas #Autowired is used for any dependency injection in Spring. Using #PersistenceContext gives you greater control over your context as it provides you with ability to specify optional elements e.g. name, properties
I think #Autowire will work same way as #PersistenceContext
https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.misc.jpa-context
When working with multiple EntityManager instances and custom
repository implementations, you need to wire the correct EntityManager
into the repository implementation class. You can do so by explicitly
naming the EntityManager in the #PersistenceContext annotation or, if
the EntityManager is #Autowired, by using #Qualifier.
As of Spring Data JPA 1.9, Spring Data JPA includes a class called
JpaContext that lets you obtain the EntityManager by managed domain
class, assuming it is managed by only one of the EntityManager
instances in the application. The following example shows how to use
JpaContext in a custom repository:
You can create the following FactoryBean to make EntityManager properly injectable, even via constructor injection:
/**
* Makes the {#link EntityManager} injectable via <i>#Autowired</i>,
* so it can be injected with constructor injection too.
* (<i>#PersistenceContext</i> cannot be used for constructor injection.)
*/
public static class EntityManagerInjectionFactory extends AbstractFactoryBean<EntityManager> {
#PersistenceContext
private EntityManager entityManager;
#Override
public Class<?> getObjectType() {
return EntityManager.class;
}
#Override
protected EntityManager createInstance() {
return entityManager;
}
}
Please note, that because we use the #PersistenceContext annotation internally, the returned EntityManager will be a proper thread-safe proxy, as it would have been injected directly at the place of usage with field injection (using #PersistenceContext).
Related
In Spring, I can inject an javax.persistence.EntityManager
into a Spring bean using the annotation #javax.persistence.PersistenceContext, like this:
#Service
public class MyRepository {
#PersistenceContext
private EntityManager entityManager;
}
This is documented in the Spring docs in chapter 20.5.2 Implementing DAOs based on plain JPA.
Is there a way to do this using CDI (specifically, Weld) if I am not using a Java EE container?
In particular, is it possible to reuse the annotation #PersistenceContext for CDI (because existing code uses it with Spring) ?
As far as I understand: When using a Java EE container, the container will interpret the annotation and inject an EntityManager. Is that correct? And is there a way to get this to work using Weld, but without a Java EE container?
I tried to inject the class above into another class using Weld (in Tomcat, without Java EE). The injection takes place, so Weld correctly creates an instance of MyRepository, however the field MyRepository.entityManager is null, as if the annotation #PersistenceContext was ignored.
What is happening (or rather, not happening) here?
You can do it this way:
create Entity Manager Factory Producer
public class EntityManagerFactoryProducer {
#Produces
#ApplicationScoped
public EntityManagerFactory create() {
return Persistence.createEntityManagerFactory("PU");
}
public void destroy(#Disposes EntityManagerFactory factory) {
factory.close();
}
}
and create Entity Manager Producer
public class EntityManagerProducer {
#Inject
transient EntityManagerFactory emf;
#Produces
#RequestScoped
public EntityManager create() {
return emf.createEntityManager();
}
public void destroy(#Disposes EntityManager em) {
em.close();
}
}
then you can use dependency injection (CDI will create one em for each request)
#Inject
EntityManager entityManager;
You have to start the CDI context in your main method
public static void main(String[] args) throws IOException {
Weld weld = new Weld();
WeldContainer container = weld.initialize();
Application application = container.instance().select(Application.class).get();
application.run();
weld.shutdown();
}
ps. If you have more then one PU use #Qualifier
While MilkMaid's answer is a sound way to go, I would just add a few more behind-the-scenes hints.
Is there a way to do this using CDI (specifically, Weld) if I am not using a Java EE container?
Short answer - there is. Weld can allow for injection of next to any object you wish to have injectable, however you need to mind who owns/manages this object. In your case, it is EntityManager which is stuff from JPA, so guess what - JPA manages the lifecycle of such object. Therefore you need to create a "wrapper" (in reality its a proxy) for such object which will be handled by CDI/Weld. And that what you need producer for.
as if the annotation #PersistenceContext was ignored.
Indeed, it is ignored. Here is a simplification of what happens. Normally, that is in EE container, Weld would make the injection happen but the real magic behind that is not a Weld core code, but rather an integration on the EE server side (who adopts Weld SPI to handle such annotations and turn them into beans which it then injects).
Generally speaking, trying to handle 'EE stuff' outside of EE containers might get tricky as you come across a lot of integration which originally happens inside the container, but you now need to handle that yourself.
Technically one could probably make the #PersistenceContext annotation work, maybe by writing a CDI extension. However, that is a nasty hack rather than anything else - one would be bending the EE-only annotation for SE usage. I would advise against it, but if you still want to go that way, the idea would be to basically make CDI think the #PersistanceContext is yet another #Inject plus provide the producer. This would mean a LOT of manual work, there is no in-built mechanism in CDI to handle that for you - this is normally the EE server's responsibility.
We're using Spring 3.1, JPA (via Hibernate) and Quartz. Typically we interact with the DB via #PersistenceContext annotation on Service beans, and either SpringMVC controllers, or GraniteDS-managed service invocation.
I'm working on writing a Quartz job that needs to interact with the database. I've tried everything I can find to get this working. I tried passing in a Spring-managed component (annotated with #PersistenceContext and #Transactional) via the jobMap, the call to entityManager.persist(o) executes, but nothing happens in the database. I also tried similar to this answer, creating a factory class to call autowireBean() on the job object. I set up the job class like so:
public class CreateAlertJob implements Job {
#PersistenceContext
EntityManager entityManager;
#Override
#Transactional
public void execute(JobExecutionContext context) throws JobExecutionException {
SomeEntity entity = new SomeEntity();
entityManager.persist(entity);
}
}
Same result, the method executes but the database is unaltered. I found this blog post which references a GitHub project. There he is using JpaInterceptor to establish a Hibernate session, but this uses the DAO pattern and I'd like to stick with using #PersistenceContext.
Clearly there is something about the Quartz thread that is preventing this from working properly? I'm about out of ideas and considering making a web service call to a SpringMVC controller just to get this working.
Since your CreateAlertJob is not created by Spring, #Transactional in it doesn't take effect.
You have the following options:
Delegate actual work to Spring bean and put #Transactional there
Use programmatic transaction management
Use AspectJ-based AOP implementation instead of Spring default implementation (but it would be overkill for such a simple problem)
I want to implement an DynamicImageResource which will be mounted in a Wicket 6.7/Spring 3.2/JPA 2 application. This DynamicImageResource shall retrieve information based on input parameters and create a response.
The question is: How can i access the DB from within DynamicImageResource.getImageData(...)? I can't inject a #PersistenceContextenter code here or a DAO via #SpringBean. My last resort would be a static PersistenceContextFactory.
Any better ideas? Or best practices?
As Wicket manages component instanciation for you, or you manually instanciate objects via their respective constructors, injection mechanisms couldn't work out of the box (the object are, per manual constructor invocation, unmanaged by your container).
Wicket provides built-in injection for Component via inheritance, the magic behind is Wicket calling componentInstanciationListeners. For every unmanaged class not inherited from an injection enabled one, you have to manually trigger the injection on your bean.
As stated in the comment, you should call Injector.get().inject(this); in your constructor in order for it to work.
To complete the whole thing, i'll past my PersistenceContextBridge Spring bean here. It wraps an EntityManager, which will be injected via #PersistenceContext. By using the Lombok annotation #Delegate all calls to the bean will be delegated to the EntityManager.
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import lombok.Delegate;
import org.springframework.stereotype.Service;
#Service
public class EntityManagerBridge implements EntityManager {
#Delegate
#PersistenceContext
private EntityManager em;
}
Now all i have to do in my Wicket component is to inject EntityManagerBridge as #SpringBean:
#SpringBean
private EntityManager em; // inject EntityManagerBridge (implements EntityManager)
public MyFancyResource() {
Injector.get().inject(this); // enable Spring injection for
}
I have a question about spring + hibernate
I always use hibernate for my develeppoment, I generate images of the tables and the class DAO
then at logic metier I make simple calls to these methods dao ....
for exemple UserDao=new UserDao () then userdao.persist() ...
Now I have intgret spring, and I do not yet understand ..
1
what is the plus made by him knowing that he is also making calls
has dao Service (the writings that manually) it does not generate the
class dao with hibernate
2
is that with spring I would not worry about manage session for
example open session, close session commit() ...
thank you in advance I would like to have an idea Ccool:
At its core, Spring is a dependency injection framework. This means that instead of doing
public class MyService
private MyDao dao;
public MyService() {
dao = new MyDao();
}
}
You can do
public class MyService
private MyDao dao;
#Autowired
public MyService(MyDao dao) {
this.dao = dao;
}
}
And Spring will automatically call the constructor and inject an instance of MyDao. The main benefit is that the code is easily unit-testable.
On top of that, it allows injecting proxies instead of the actual implementations directly. These proxies will indeed handle the transaction management for you, and more (exception translation, security checks, etc.).
So instead of explicitely opening, committing and rollbacking transactions, you would simply annotate a service method with #Transactional, and Spring would open, commit/rollback the transaction. And the transaction context would automatically propagate to the nested service calls.
This short answer is only to give you an idea. To learn more, read about dependency injection, and read the Spring documentation.
Use Spring annotations like #Service for service classes, #Repository for Dao classes and #Controller for action controllers. Use of #Transactional on service class or methods is suffice to carry out transactions.
EntityManager is not thread-safe by definition.
Servlets specs says that in non-distributed environment and without implementing SingleThreadModel, there is only one servlet instance per definition.
Therefore, in Java EE when you inject an EntityManager through the #PersistenceContext into Servlet's field - it's not thread safe:
public class MyServlet extends HttpServlet {
// Not thread-safe, should be using EMF instead.
#PersistenceContext
private EntityManager em;
}
Is this correct to say that even though the default scope of Spring beans is singleton, the EntityManager is thread-safe as the Spring uses ThreadLocal to bind its transaction and EntityManager to it?
Is the above Servlets example still valid in Spring? Is it still not thread-safe?
Does the ThreadLocal approach works only for Spring managed beans and plain servlet is not one of those?
As far as I remember, it's the container responsibility to inject the EntityManager. In Glassfish Java EE implementation, it was the application server who discovers the #PersistenceContext as injection point.
How does it look like in Spring? Is the Spring Framework responsible for discovering those annotations or it's responsibility of the JPA implementor?
Question 2, 3, and 4 -- Spring does not pay attention to any class that is not a Spring Bean. Therefor Spring does not pay attention to you MyServlet class.
Therefore the answer for
2) is no
3) only Spring managed Beans
4) it is Springs responsibility, because Spring is the Container
For Question 1). It works this way, so the usage of an Spring Injected Entity Manager is effective thread save.