I’m using EntityManager in may Dao layer without #PersistenceContext but Dao method is calling service method which is marked as #Transactional. My question is should I use EntityManagerFactory in dao layer and every time get EntityManager to keep thread safety or it’s handled already?
Dao layer:
#RequiredArgsConstructor
public class UserDaoImpl {
private final EntityManager em;
public void save(User user){
em.persist(user);
}
}
Service layer:
#RequiredArgsConstructor
public class UserService {
private final UserDao userDao;
#Transactional
public void save(User user) {
userDao.save(user);
}
}
Tnx!
just add #PersistenceContext to your Entity Manager and the container will handle it for you, but if you are not in JEE environment so create your own entity manager factory, but I think in your current case the entity manager will still null. Also you must create you persistence unit XML file, and take attention in transaction-type, it must be JTA if you use #PersistenceContext and it should be RESSOURCE_LOCAL if you will create your own Entity Manager Factory.
This stackoverflow question Is EntityManager really thread-safe? already got answer to your question.
And this one "Future-Proofing Java Data Access - DAO Pattern Done Right" shows how to design DAO layer.
But if you are using Spring and Spring Data repository then I would suggest defining repository using CrusRepository or JpaRepository interface.
That would offload your concerns regarding EntityManager handling to Spring.
Related
I am working on a project where I have separated EJB such that they only carry out the business logic but not performing the queries. Then I also have the DAOs that performs the queries. For me to use the DAOs, I inject the DAOs in the EJB and with a method annotated #PostConstruct, I set the EntityManager in the DAO with the EntityManager injected in the bean like bellow:
public class ClazzDao implements ClazzDaoI{
private EntityManager em;
public void setEm(EntityManager em){
this.em = em;
}
public List<Entity> list(){
return em.createQuery("FROM Entity e").getResultList();
}
}
And the EJB
#Stateless
public class ClazzBean implements ClazzBeanI{
#PersistenceContext
private EntityManager em;
#Inject
private ClazzDaoI clazzDao;
#PostConstruct
private void init(){
clazzDao.setEm(em);
}
public BigDecimal sendEmailToMembers(){
List<Entity> members = clazzDao.list();
//do some stuff with data like say send emails...
}
}
Is there a way that I can make the DAOs use the entity manager injected in the EJB without setting it at the #PostConstruct of the EJB?
You can use inject capability only in container managed beans. You dao class is outside of container management no way to inject the EntityManager into this object. Put you class into container management (EJB/CDI) if you need injection capability. By the way avoid to use unnecessary interfaces use non interface view instead.
Make Sure Are you using JAVA EE 6 OR HIGHER, Make the ClazzDao as Managed Bean, means either #ApplicationScoped/#SessionScoped
#ApplicationScoped
public class ClazzDao implements ClazzDaoI
CDI can inject ClazzDao ManagedBean.
I am developing a project with spring framework.
I have following architecture: all database code is in dao classes, all application logic is in service classes, http requests are processed using spring mvc rest controllers.
#Repository
public class UserDao {
#PersistenceContext
private EntityManager em;
public void editUser(User user) {
...
}
}
#Service
public class UserService {
#Autowired
private UserDao userDao;
#Transactional
public void editUser(User user) {
...
}
}
#RestController
#RequestMapping(value = "/UserCtrl", produces = "application/json;charset=UTF-8")
public class UserCtrl {
private static final Logger logger = LogManager.getLogger(AppConfig.LOGGER_NAME);
#Autowired
private ApplicationContext appContext;
#RequestMapping(value = "/editUser")
public ActionResult editUser(#ModelAttribute User user) {
ActionResult rslt = new ActionResult();
try {
UserService userService = appContext.getBean(UserService.class);
userService.editUser(user);
rslt.setSuccess(true);
} catch (Exception ex) {
logger.error("editUser", ex);
rslt.setSuccess(false);
}
return rslt;
}
}
This code works correctly.
One thing I cannot understand is how aop proxy of UserService bean starts transaction, when EntityManager is injected only in UserDao class. Can somebody explain me how this works and how EntityManager lifecycle is managed by spring framework ?
Any help appreciated.
The TransactionManager is responsible for managing the transaction boundaries
in Spring Framework.
When you annotate the business method with #Transactional you are instrumenting the method with an aspect.
Before executing the method, this aspect interact with TransactionManager which decides if it is necessary to create a new Transaction or use a preexisting one. In the case of create a new Transaction, a new Entity Manager is created from EntityManagerFactory and is associated to the current thread alonside with the Transaction.
The EntityManager is responsible to iterate with the database. When you inject it with #PersistenceContext, Spring injects an proxy to the EntityManager.
Whenever an operation is executed in the EntityManager proxy it looks the EntityManager associated with the thread.
Based on the snippet of code you provide you are using spring with some implementation of JPA you are using J2EE container for your web application and bases on my guess I think this is good article about how things works.
Basic concepts :
EntityManager - A class that manages the persistent state(or lifecycle) of an entity.
Persistence Unit - is a named configuration of entity classes.
Persistence Context - is a managed set of entity instances. The entities classes are part of the Persistence Unit configurations.
Managed Entities - an entity instance is managed if it is part of a persistence context and that Entity Manager can act upon it.
Based on this article you use Container Managed EntityManager by using #PersistenceContext
When a container of the application(be it a Java EE container or any other custom container like Spring) manages the lifecycle of the Entity Manager, the Entity Manager is said to be Container Managed. The most common way of acquiring a Container Managed EntityManager is to use #PersistenceContext annotation on an EntityManager attribute.
And the injection is like this :
A Transaction Scoped Entity Manager is returned whenever a reference created by #PersistenceContext is resolved.
and
Every time an operation is invoked on an Entity Manager, the container proxy(the container creates a proxy around the entity manager while instantiating it ) checks for any existing Persistence Context on the JTA Transaction. If it finds one, the Entity Manager will use this Persistence Context. If it doesnt find one, then it will create a new Persistence Context and associates it with the transaction.
So the lifecycle of of entity manager is managed by your container and
we work with an instance of EntityManager, the only role of EntityManager is to determine the lifetime of the Persistence Context. It plays no role in dictating how a Persistence Context should behave. To reiterate, Persistence Context is a managed set of Entity instances. Whenever a transaction begins, a Persistence Context instance gets associated with it. And when a Transaction ends(commits for example), the Persistence Context is flushed and get disassociated with the transaction.
In the nutshell container instantiate your EntityManager by the EntityManagerFactory you provide and manage it's lifecycle but inject the proxy of EntityManager for you. The TransactionManager is responsible for creating, commiting and ... tranactions based on annotations you provide ,whenever it begins the transaction the PersistancecContext associated with it and when the tranasction ends it commites the state of PersistenceContext. The EntityManager works with PersistenceContext and if it's not provided the EntityManager creates one. The EntityManager is threadsafe as long as it holds no state and the state (PersistenceContext) is attached to current tranasction.
Hope this helps.
How do I achieve a complete transaction where a service class requires more than one data access object. Assuming I have the following structure.
Currently, if my dao2 failed, the dao1 still being committed to the database which I do not want it to happen. However, I need my DAO to be reusable.
public class mainService(){
dao1.store(obj1);
dao2.store(obj2);
}
And my dao is written in this way.
Dao 1
private EntityManager entityManager;
#Transactional
public void store(Object obj1){
entityManager.persist(obj1);
}
Dao 2
private EntityManager entityManager;
#Transactional
public void store(Object obj2){
entityManager.persist(obj2);
}
Please help.
Make this happen in one transaction.
#Transactional
public void mainService(..){
dao1.store(obj1);
dao2.store(obj2);
}
Only one transaction will be created, and if dao2 fails, dao1 won't be committed as well. And remove #Transactional from store method. Making DB level methods transactional it's not a good idea. This level might be two low in some cases.
The obvious answer is to use:
private EntityManager entityManager;
#Transactional
public void store(Object obj1, Object obj2){
entityManager.persist(obj1);
entityManager.persist(obj2);
}
What's happened is that you have become hung up on using DAOs. The DAO is dead! If you look at the EntityManager API you will notice that it actually looks very much like a DAO type of interface. So just use it directly where ever you would normally consider using a DAO.
In your case, you should mark mainService() with #Transactional too, For transaction propagation rule is PROPAGATION_REQUIRED by default , and then both dao1.store() and dao2.store() with be under the same transaction.It's OK to keep dao1.store() and dao2.store() #Transactional, they will realize that there is already a transaction and then join the transaction.
I'm working on a desktop application using Java SE 7. The application uses multiple threads and in each thread that is created a DAO class is injected to gain access to my database. As persistence layer i'm using EclipseLink and JPA. The EntityManager is injected into my DAO class using constructor injection and since it is not thread safe, I went for the approach using a Provder like this:
public PluginInstanceJpaController implements IPluginInstanceDao {
private EntityManager em;
#Injected
public PluginInstanceJpaController(Provider<EntityManager> emp) {
this.em = emp.get();
}
#Transactional
public void create(PluginInstance foo) throws Exception {
em.persist(foo);
}
}
However, the very same EntityManager instance is injected into each DAO. For setting that up I used the JpaPersistModule as it is provided by guice and i'm sure that there are not singletons in my setup so far.
Does anyone know how to tell guice to create a new instance of the EntityManager when injecting?
In another approach I tried custom providers for the EntityManagerFactory and the EntityManager and leaving the JpaPersistModule out of my business. This resulted in a EntityManager instance per DAO, however #Transactional annotated methods were not intercepted then.
I'd appreciate any solution to this issue.
Thanks so far!
--- EDIT ---
The DAO classes are injected into a Runnable that is using them. The Runnable is also provided through a Provider. My module configuration looks something like this:
public class RepositoryModule extends AbstractModule {
#Override
protected void configure() {
// DAO bindings
bind(IObjectStoreDao.class).to(ObjectStoreJpaController.class);
bind(IPluginInstanceDao.class).to(PluginInstanceJpaController.class);
}
#Provides
public PluginMonitor newMonitor(IPluginInstanceDao plugDao, IObjectStoreDao osDao) {
PluginMonitor m = new PluginMonitor();
m.setPluginInstanceDao(plugDao);
m.setObjectStoreDao(osDao);
return m;
}
}
Here PluginMonitor is my Runnable. The Injector itself is created in my main thread... might this have been the issue?
This is very similiar issue: How Guice injects singletons and non-singletons into multiple threads
To your DAO, this should work.
public PluginInstanceJpaController implements IPluginInstanceDao {
private Provider<EntityManager> emProvider;
#Injected
public PluginInstanceJpaController(Provider<EntityManager> emp) {
this.em = emp;
}
#Transactional
public void create(PluginInstance foo) throws Exception {
em.get().persist(foo);
}
}
You should use Jpa Persistence Module or create custom EntityManager provider, which will return new EntityManager for each get() call, also it can be implemented with ThreadLocal to ensure EntityManager will be shared across thread.
I'm not familiar with JPA, but hopefully I can still help :-)
If you look at the source for EntityManagerProvider, you can see there's a ThreadLocal<EntityManager>. So by default, each thread should have its own EntityManager. That leads me to believe the problem is elsewhere. Are you sure that no module is setting the EntityManager to be a singleton? How are you determining that all the EntityManagers are the same object? Each DAO is definitely on its own thread? Can you provide details on how FooDao is configured in your module and how a new FooDao is provided to each thread?
Also, you should be fine to write your constructor as:
#Inject
public FooDao(EntityManager emp) {
this.em = emp;
}
Guice will do the magic for you of determining that EntityManagerProvider provides EntityManager instances, and will call get() on the EntityManagerProvider instance to get an EntityManager to give to your constructor.
My Spring+Hibernate configuration files are small and super tight. I use auto scanning to find my model entities/daos.
I don't want to have to write a DAO + DAOImpl for EVERY Entity in my hierarchy.
Some may qualify to have their own, like if they have complex relationships with other entities and require more than basic CRUD functionality. But for the rest...
Is there any way to circumvent the defacto standard?
Say, something like a generic DAO, ex:
http://www.ibm.com/developerworks/java/library/j-genericdao/index.html
Then I can do something like
GenericDao dao = appContext.getBean("genericDao");
dao.save(car);
dao.save(lease);
Is this possible with annotations? I don't want to have to configure anything in xml. If I cannot do above, is it still possible to have one GenericDaoImpl.java with something like:
#Repository("carDao")
#Repository("leaseDao")
class GenericDaoImpl extends CustomHibernateDaoSupport implements GenericDao {
...
}
and then
GenericDao dao = appContext.getBean("carDao");
dao.save(car);
dao = appContext.getBean("leaseDao"); //carDao is garbage coll.
dao.save(lease);
Is this practical at all?
Using generics, you might try something like this:
#Repository
#Transactional
public class GenericDAOImpl<T> implements GenericDAO<T> {
#Autowired
private SessionFactory factory;
public void persist(T entity) {
Session session = factory.getCurrentSession();
session.persist(entity);
}
#SuppressWarnings("unchecked")
public T merge(T entity) {
Session session = factory.getCurrentSession();
return (T) session.merge(entity);
}
public void saveOrUpdate(T entity) {
Session session = factory.getCurrentSession();
session.saveOrUpdate(entity);
}
public void delete(T entity) {
Session session = factory.getCurrentSession();
session.delete(entity);
}
}
The content may be different, but the general idea is applicable.
You should be able to then autowire the DAO in your controller and service classes by using
#Autowired
private GenericDAO<Car> carDao;
You can combine Spring/Hibernate with JPA, which provides the EntityManager for a large amount of basic persistence tasks:
#Service
public class CarService {
#PersistenceContext
private EntityManager em;
public void saveCarAndLease(Car car, Lease lease) {
em.persist(car);
em.persist(lease);
}
}
It will also handle transactions and simple queries without needing to write a DAO. For the more complex operations, you can still write a DAO and fall back to Hibernate's SessionFactory (although JPA is an option here too).
Some tutorials suggest you should still write the DAO for abstraction of the JPA plumbing. However, I have personally found this unnecessary (JPA has a very small integration footprint), and in fact this is also the way Spring Roo deals with the data layer behind the scenes.
Have you tried to use Spring Data. I mean to say Spring JPA where you can use repositories.
You can eliminate writing all stuffs for each entity.