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.
Related
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;
}
}
}
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?
I am a long time Seam user who tries to move to Java EE7, JSF2.2 and CDI now.
In Seam you tend to use EntityManagers with extended scope most of the time (in the Seam Conversation Scope). You don't get any LIEs on Ajax request etc.
I am trying to do it in a similar way with Java EE7 and CDI but somehow the injected EntityManager is only transaction scoped. When I get a ajax request in the entities that were loaded before are not managed anymore.
I am using the new javax.faces.view.ViewScoped and javax.transactional.Transactional on my CDI bean.
My Producer:
#PersistenceContext(unitName = "primary", type = PersistenceContextType.EXTENDED)
private EntityManager entityManager;
#Produces
#Default
#Dependent
public EntityManager getEntityManager() {
return entityManager;
}
And my CDI bean:
#Named
#ViewScoped
#Transactional
public class TestBean implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
#Inject
EntityManager entityManager;
Logger log = Logger.getLogger(TestBean.class);
private TestEntity lastTest = null;
public void testAdd(){
TestEntity test = new TestEntity();
test.setVal("Test "+System.currentTimeMillis());
entityManager.persist(test);
entityManager.flush();
log.infov("Created test entity {0}", test);
lastTest = test;
}
public void testRead(){
List<TestEntity> test = entityManager.createQuery("select t from TestEntity t").getResultList();
for(TestEntity t: test){
log.infov("Found {0} managed {1}",t,entityManager.contains(t));
}
if(lastTest!=null){
log.infov("Last Test {0} managed {1}",lastTest,entityManager.contains(lastTest));
}
}
So when I first call testAdd() via Ajax it creates a new test entity. When I then call testRead() it gets all test entities and checks that the last created test entity is still managed (which it should if it is an EntityManager with an extended persistent context). But entityManager.contains(lastTest) always returns false.
What am I doing wrong?
I believe I can't use #PersistenceContext directly in the CDI bean. So how do I get the desired (Seam like) behaviour?
When you specify that an injected EntityManager is an extended persistence context, all object instances remain managed. Extended persistence contexts can only be used within Stateful session beans.
This is according to JBOSS documentation: https://docs.jboss.org/ejb3/app-server/tutorial/extended_pc/extended.html.
Consider packaging your insert/update/delete operations into EJBs while simple read from database can be through CDI beans. But more complex operations involving multiple reads and writes as well as transaction should be within EJBs.
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">
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.