-
-
Notifications
You must be signed in to change notification settings - Fork 4.1k
Refactoring play-jpa - Got rid of ThreadLocal #6777
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
marcospereira
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Matthias,
I was thinking about this API also and was planning to do something different of what you did. My idea is to separate the responsibility of get the EntityManager and the execution of transactions completely so that the JPAApi won't be responsible to expose/create/retrieve EntityManagers.
The complete surface of JPAApi would be:
public interface JPAApi {
public <T> T withTransaction(Function<EntityManager, T> block);
public <T> T withTransaction(String name, Function<EntityManager, T> block);
public <T> T withTransaction(String name, boolean readOnly, Function<EntityManager, T> block);
public <T> T withTransaction(Supplier<T> block);
public void withTransaction(Runnable block);
public <T> T withTransaction(String name, boolean readOnly, Supplier<T> block);
}And then, we can inject a EntityManager resolver into the DefaultJPAApi. This resolver could use the Http.Context right now, but it will eventually migrate to use #6798. The way I see #6798 evolving, we can even have controllers like this:
public MyController extends Controller {
private EntityManager em;
@Inject
public MyController(EntityManager em) {
this.em = em;
}
}Anyway, we are not there yet. See my other comments.
| * | ||
| * @return EntityManager for the specified persistence unit name | ||
| */ | ||
| public EntityManager em() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we should deprecate this instead of remove it.
| * @return code execution result | ||
| */ | ||
| @Override | ||
| public <T> T withTransaction(String name, boolean readOnly, Http.Context ctx, boolean keepTransactionOpen, Function<EntityManager, T> block) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we are mixing layers here. We now have the (lower) Persistence layer depending on the (higher) HTTP layer. One implication here is now that to test a model/service object, I will need a Http.Context.
|
Outdated. Replaced by #8616 |
Replaces #6013
As we know to run code within a JPA transaction the preferred way is to call
With this PR an entity manager now always gets passed to all the various
withTransactionmethods. The em doesn't get stored in aThreadLocalanymore.Only when using
@Transactionalthe entity manager still will be stored in theHttp.Contextso we can access and (re-)use it later from within the controller's action methods. But I did change how this happens. Instead of just accessingHttp.Context.current()you now have to explicitly pass thecontextin which the em should get stored towithTransaction(happens inTransactionalAction.java).Eventually, to retrieve the em we now have to pass a context to
JPA.em(ctx).With this changes
JPAEntityManagerContextis becoming "just" a simple helper class which just makes it easier to store and read entity managers from a http context.In future we can remove
JPA.em()(it's deprecated now) in favor ofJPA.em(ctx)- actually it's just a shortcut forJPAEntityManagerContext.em(ctx).This should make
play-jpaready for the removal of the http context threadlocal which I think is targeted for a future play version. (It should work nicely with the changes in #6473 done by @gmethvin)One more thing:
In
@TransactionalActionwe tellwithTransactionto keep the em and transaction open so it doesn't get closed immediately but only after the future has completed. I am not entirely sure if this should be managed here or if I should add awithTransactionthat returns aCompletionStage<T>and manage it there. Related to #6489