I was reading a question about EJBContext.setRollbackOnly() method in a mock exam, one of the accepted answers is
It cannot be used by JPA Entities. [because] Entities do not have EJBContext. Remember that persistent entities are not same as Entity Beans. Entity Beans do not exist in EJB 3.x.
API reference states that
The EntityContext interface provides an instance with access to the container-provided runtime context of an entity bean instance.
and EntityContext extends EJBContext.
Now, what does it mean that persistent entities are not same as Entity Beans?
Related
I am new to EF.
Is it possible to inject entities in an EF context?
Taking the case from Microsoft documentation: https://learn.microsoft.com/en-us/ef/core/miscellaneous/configuring-dbcontext
Let's say, I have different implementations of blog. When it comes to properties that require persistence, they are the same and implement IBlog interface to reflect that.
How should I define BloggingContext to work with any of the blogs? I cannot use IBlog. DBSet would not accept an interface as a generic reference type to be used as entity type.
Do I have do define a base abstract class for my blogs in order to inject them in EF context? Is this the only way?
I'm designing my database and I reached the situation that an Entity itself requires to access database.
I read Why sometimes a reference to an EntityManager inside JPA entities is needed.
And I'm curious about the possibility of accessing an EJB in EntityListener.
public class MyEntityListener {
#PrePersist
private void onPrePersist(final Object object) {
// find an EJB
// and set those required values
// which each resides in a specific table.
}
}
Is this possible or (or and) preferred?
I found an answer.
CDI injection in EntityListeners
https://blogs.oracle.com/arungupta/entry/jpa_2_1_early_draft
It seems possible, according to JSR 338: JavaTM Persistence 2.1.
3.5.1 Entity Listeners
Entity listener classes in Java EE environments support dependency injection through the Contexts and Dependency Injection API (CDI) [ 10 ] when CDI is enabled[43]. An entity listener class that makes use of CDI injection may also define lifecycle callback methods annotated with the PostConstruct and PreDestroy annotations. These methods will be invoked after injection has taken place and before the entity listener instance is destroyed respectively.
The persistence provider is responsible for using the CDI SPI to create instances of the entity listener class; to perform injection upon such instances; to invoke their PostConstruct and PreDestroy methods, if any; and to dispose of the entity listener instances.
I have an in-application cache of some plain simple Entity beans (EJB 3.1, Glassfish, EclipseLink), so that I don't have to look them up in database with findById each time since application needs to be fast. These entity beans are read-only.
So for example entity bean Country or Currency is in the local cache.
Some process in the Java EE application occurs that wishes to update a complex entity bean (i.e. Customer), which uses the simple beans above (Country, Currency...).
What happens then is that, because the connection of simple entity beans to the JPA context is lost, when .merge() is attempted on the Customer bean, JPA wishes to save the simple entity beans as new records in the database, although these exist 100% in the database already, so I guess this is a "detached entity" problem.
Example.
Country country = getFromCacheByName("GB"); // detached entity, but exists in database
Customer customer = getCustomerFromJPA(); // existing JPA attached entity
customer.setCountry(country);
EntityManager.merge(customer); // pseudo code
How to fix the last line, or the bean (Customer) itself, so that it does not try to save the dependant object (Country) on .merge() ?
Thank you.
You should do a find() or merge() on the country before setting it in the Customer. Also, ensure it has the correct Id.
Merge on Customer should also work though, it is odd that it would attempt to insert the country if its Id was existing, but this could depend on how you have configured things. Are you cascading the merge on the country relationship?
Note that EclipseLink has its own cache. So your application cache is probably not needed.
If i havea JPA class Person and Person has reference to a JPA class Address. If I call Person.persist(), will Address.persist() be called implicitly?What if the hierarchy was longer. Would all the child classes be persisted implicitly?
From the JPA specification:
The semantics of the persist operation, applied to an entity X are as
follows: ...
the persist operation is cascaded to entities referenced by X, if the relationships from X to these other entities is annotated with the
cascade=PERSIST or cascade=ALL annotation element value or speciļ¬ed
with the equivalent XML descriptor element.
That may seem obvious but I've seen contradictory statements: Is JPA part of EJB 3.0? I'm no specialist and it's quite confusing for me.
If so, JPA manipulates Entity Beans? These entity beans being the interface between the persistence layer and the business layer implementing the logic with stateless beans?
The underlying question for me is how to implement a "search for user based on various criteria" function, where the "search" request -its string representation- should be built? I mean, if JPA is not part of EJB, my beans shouldn't be aware of the data model, right?
Where is the boundary?
Is JPA part of EJB 3.0 ?
Yes and no... Yes because every application server claiming to implement EJB 3.0 spec must also provide JPA implementation. No because JPA can be easily outside of EJB, in standalone applications or Spring-managed ones.
JPA manipulates Entity Beans ?
Entity beans was a scary idea in pre-3.0 EJBs. JPA uses the term entities to distinguish itself from the disgraceful history. But yes, JPA entities are a way to map database tables to plain Java objects. In principle changes made to object are propagated to database and vice-versa (oversimplification).
As I said, JPA does not have any dependency on EJB (considered as stateless and stateful session beans) and the other way around. But there is nothing preventing you from using JPA in EJB.
In your scenario you'll have a stateless EJB constructing the query and interacting with the database via JPA. Technically speaking you will call methods on EntityManager injected to your bean:
#Stateless
public class SearchService {
#PersistenceContext
private EntityManager em;
public List<User> findUsersBornAfter(Date date) {
return em.
createQuery("SELECT u FROM User u WHERE u.birthDate > :birthDate ORDER BY name").
setParameter("birthDate", date).
getResultList();
}
}
As you can see the business layer is aware of the data model (obviously), but there is no dependency on EJB/business services as far as entities are concerned. In this example JPQL (query) is formed in the service layer and User is a JPA entity. Calling getResultList() causes the JPA provider to translate JPQL to SQL, run the query and transalte the results back to User object instances.
Is the border between EJB and JPA clear now?
A couple of notes:
when it comes to the JSR, JPA 1.0 was part of EJB 3.0. See here , JPA 2.0 is a separate JSR (see here)
"entity beans" are EJB pre-3.0, and they are luckily dead. They are succeeded by JPA.
when it comes to dependencies - JPA does not depend on EJB, and EJB does not depend on JPA. However, EJB can handle injection of JPA entity manager
you can use either of them standalone
each application server supports both
Adding to BalusC's answer, from Wikipedia - Enterprise JavaBean:
Note that the current EJB 3.1 specification does not detail how an application server provides persistence (a task delegated to the JPA specification), but instead details how business logic can easily integrate with the persistence services offered by the application server.
The integration takes away some pain points from JPA, namely the rather verbose and noisy starting and committing/rollbacking a transaction and scoping the extended persistence context (that last one only for statefull session beans).
Adding to Bozho's answer:
In EJB 3.0, JPA 1.0 was part of EJB but as a sub-spec and useable outside EJB and outside Java EE.
In EJB 3.1, JPA has been completely split-off from EJB and JPA 2.0 is 100% a separate JSR.
From Wikipedia - Java Persistence API:
Enterprise JavaBeans
The EJB 3.0 specification (itself part of the Java EE 5 platform) included a definition of the Java Persistence API. However, end-users do not need an EJB container or a Java EE application server in order to run applications that use this persistence API.[1] Future versions of the Java Persistence API will be defined in a separate JSR and specification rather than in the EJB JSR/specification.
The Java Persistence API replaces the persistence solution of EJB 2.0 CMP (Container Managed Persistence).