children extended from parent DAO - entity-framework

I have a problem. I have a parent DAO:
public abstract class ParentDAO<T> {
#PersistenceContext
private EntityManager entityManager;
public EntityManager getEntityManager() {
return entityManager;
}
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
private EntityManager em() {
if (entityManager == null)
throw new IllegalStateException("The entity manager is not set");
return entityManager;
}
}
from which extends another children DAOs.
When I want to do some operation with children entity in children DAO, I must get EntityManager object from parent class or change the entityManager object declaration to protected which is bad OOP design. Is there another way to do this? Because when I have 100 DAO children's then I must get the entityManager from parent DAO for every new children.

yes incase you are using spring, you can just use "parent" attribute to give the base bean id.... so create one base bean object in this case entity manager and add it as parent in ur subclassed bean declarations.... look for extends + parent in spring bean declaration.

Related

Is it possible to inject a context specific PersistenceContext?

In a jsf application data is managed injecting a PersistenceContext.
#PersistenceContext(unitName = "MyPU")
private EntityManager em;
PersistenceContext is static and choosen at compile time. Is there a way to inject a different PersistenceContext based on the user ? My idea is to enforce authorization checks on database side too, so if there is a hole in application security the user cannot access or modify restricted data.
Create some factory :
#Stateless
public class PersistenceContextFactory {
#PersistenceContext(unitName="MyPU")
private EntityManager emPU;
#PersistenceContext(unitName="MyOtherPU")
private EntityManager emOtherPU;
public EntityManager getEntityManager(User user) {
if(user.hasSomeRight()) {
return emPU;
} else {
return emOtherPU;
}
}
}

CDI with EntityListener and timing issue?

I'm trying to do this.
public class MyEntityListener {
#PrePersist
private void onPrePersist(final Object object) {
// set object with value fetched via onPostConstruct
}
#PostConstruct
private void onPostConstruct() {
// fetch some value using entityManager
}
#PersistenceContext
private EntityManager entityManager;
}
When I persist and instance via EJB, the entityManager is different instance from that of the EJB.
onPrePersist is executed (before or) regardless of postConstruct.
Is this normal?

How do I create a separate entity manager for bulk operations in a JTA environment?

In JPA, when doing bulk operations such as this
update LogEntry e set e.customer = null where e.customer.id = :cid
It is recommended to use a separate entity manager to avoid breaking synchronization, according to this: UPDATE SET Queries in JPA/JPQL
For example, the EntityManager may not be aware that a cached entity object in its persistence context has been modified by an UPDATE query. Therefore, it is a good practice to use a separate EntityManager for UPDATE queries.
How do I create a separate entity manager in a JTA environment such as Wildfly using hibernate? Do I need to create a separate persistence unit for bulk operations?
EDIT: Given I dont need a separate PU for bulk operations, is this a sufficient way of solving it using a new transaction?
#Transactional
public class JpaCustomerRepository implements CustomerRepository {
#Inject
private EntityManager em;
...
#Override
public Customer remove(long id) {
CustomerEntity entity = em.find(CustomerEntity.class, id);
if (entity != null) {
updateLogEntriesToNull(entity);
em.remove(entity);
return entity;
} else {
return null;
}
}
#Transactional(value=TxType.REQUIRES_NEW)
public void updateLogEntriesToNull(CustomerEntity entity) {
em.createNamedQuery(LogEntry.updateCustomerToNull)
.setParameter("cid", entity.getId())
.executeUpdate();
}
...
}
Where LogEntry.updateCustomerToNull is the bulk query.
Answer: This does not work because the interceptor is not invoked when called from inside the same class.
EDIT2: Following the suggestions from Andrei, this should work:
#Transactional
public class JpaCustomerRepository implements CustomerRepository {
public static class BulkUpdater {
#Inject
private EntityManager em;
#Transactional(value=TxType.REQUIRES_NEW)
public void updateLogEntriesToNull(CustomerEntity entity) {
em.createNamedQuery(LogEntry.updateCustomerToNull)
.setParameter("cid", entity.getId())
.executeUpdate();
}
}
#Inject
private EntityManager em;
#Inject
private BulkUpdater bulkUpdater;
...
#Override
public Customer remove(long id) {
CustomerEntity entity = em.find(CustomerEntity.class, id);
if (entity != null) {
bulkUpdater.updateLogEntriesToNull(entity);
em.remove(entity);
return entity;
} else {
return null;
}
}
...
}
Testing confirms that the interceptor gets called twice.
The recommendation is valid only if you also do other stuff with the EntityManager (when there is a risk of manipulating/reading the same entities as the BULK UPDATE). The easiest solution: make sure that this BULK UPDATE is executed in a separate service, within a new transaction. No need to create a separate PU (persistence unit) for bulk operations.

How to get entityManager by using an entity class

How to reach the entity manager which managed the entity. I mean; suppose that i have an entity reference in the sessionBean, how can i get entityManager of this entity belonged one?
I had already tried (plz see getEntityManagerOfEntity() method) contains method of em; but it does not work.
Thx
bgrds
#Stateless(name = "MainManager", mappedName = "MainManager")
#TransactionManagement(TransactionManagementType.CONTAINER)
#Interceptors(value = { PerformanceMonitor.class, ProfileInterceptor.class })
public class MainManagerBean implements MainManager, MainManagerLocal
{
private Logger logger = Logger.getLogger(this.getClass());
#PersistenceContext(unitName = "DSApp")
private EntityManager manager;
#PersistenceContext(unitName = "DSIX")
private EntityManager integrationManager;
#Resource
SessionContext ctx;
public EntityManager getEntityManagerOfEntity(SuperEntity superEntity)
{
if (manager.contains(superEntity))
return manager;
else if (integrationManager.contains(superEntity))
return integrationManager;
return null;
}
public SuperEntity findByPrimaryKey(SuperEntity superEntity)
{
getEntityManagerOfEntity(superEntity).setFlushMode(FlushModeType.COMMIT);
return dao.findByPrimaryKey(getEntityManagerOfEntity(superEntity), superEntity);
You cannot backtrack the EntityManager from an entity using the JPA API, even when it is still managed.
What you can do, if you have references to different EMs in your bean and the entity is managed, is to check the right EM by calling em.contains(entity).
In most cases it is not really important to know, which EM has fetched an entity originally, since you can merge the entity into any persistence context and continue working with it.

Entity states between EJB and Jersey

I'm a novice.
Does Jersey and EJB hold the same EntityManager scope?
Should I have to pass the EntityManager to EJB for same persistence context?
The primary target usage is JTA.
#Stateless
class MyEJB {
public MyEntity find(Long id) {
...
}
#PersistenceContext;
EntityManager entityManager;
}
class MyResource {
#GET
#Path("/myentity/{id}");
public MyEntity get(#PathParam("id") final long id) {
final MyEntity found = myEjb.find(id);
// is found's state detached?
// should I have to reattach?
found.setDate(new Date());
return found;
}
#EJB
private MyEjb myEjb;
#PersistenceContext;
EntityManager entityManager;
}
Does Jersey and EJB hold the same EntityManager scope?
Should I have to pass the EntityManager to EJB for same persistence context?
I don't think that your wording is correct, but they can share the same EntityManager instance, and you have chosen the right way (through injection). Have a look at this chapter of the Java EE 6 Tutorial:
To obtain an EntityManager instance, inject the entity manager into the application component:
#PersistenceContext
EntityManager em;
So, once again, your approach is correct. With regards to the questions in the code comments: the fact that MyEntity is attached or detached, it depends on the implementation of the find method in your EJB. If you do the following, it will be attached:
public MyEntity find(Long id) {
return entityManager.find(MyEntity.class, id);
}
Finally, doing this way, if you have chosen JTA to use container managed transactions, the transactions will be automatically bounded with the natural boundaries of MyBean's methods. In order to have JTA transactions, you have to use this line in persistence.xml file:
<persistence-unit name="em" transaction-type="JTA">