jakartaee / persistence

https://jakartaee.github.io/persistence/
Other
191 stars 55 forks source link

easy access to the JDBC connection associated with the EM #432

Closed gavinking closed 11 months ago

gavinking commented 12 months ago

JPA currently provides no easy way to just run some JDBC code within the transaction/connection associated with the EntityManager. This isn't such a big deal when using JPA inside a container, but it's a pretty big limitation when using it in standalone mode.

Hibernate has an API like this, as part of our Session:

    /**
     * Perform work using the {@link java.sql.Connection} underlying by this session.
     *
     * @param work The work to be performed.
     *
     * @throws HibernateException Generally indicates wrapped {@link java.sql.SQLException}
     */
    void doWork(Work work) throws HibernateException;

    /**
     * Perform work using the {@link java.sql.Connection} underlying by this session,
     * and return a result.
     *
     * @param work The work to be performed.
     * @param <T> The type of the result returned from the work
     *
     * @return the result of calling {@link ReturningWork#execute}.
     *
     * @throws HibernateException Generally indicates wrapped {@link java.sql.SQLException}
     */
    <T> T doReturningWork(ReturningWork<T> work) throws HibernateException;

I propose we add something very similar, or even almost identical to EntityManager.

gavinking commented 12 months ago

Please see draft proposal in #433

hantsy commented 11 months ago

I would like unite the naming to use withConnection or doWithConnection directly, the run/call will lead developers to think it will accept a Runnable or Callable as parameter at the first sight.

gavinking commented 11 months ago

Well, actually I quite deliberately chose "run" and "call" to make you think of the difference between Runnable and Callable. The difference between these two operations is very much analogous.

I'm not very keen on your suggested convention because:

  1. the names of the two operations are asymmetric, and
  2. "with" vs "doWith" isn't suggestive at all: I suppose you mean to stick "do" on the one which doesn't return a value, but even that's not 100% obvious.

Do you have a different suggestion?

gavinking commented 11 months ago

Note that "executeWith" and "computeWith" work and are very clear, but they're also quite verbose. (I could live with them if that's what others prefer.)

hantsy commented 11 months ago

I just see some examples like these, eg. Micronaut Data use withXXX in the XXXOperations or TransactionsOperator and Hibernate Reactive SessionFactory itself contains withSession/withTransaction, https://github.com/hantsy/quarkus-sandbox/blob/master/resteasy-reactive-hibernate/src/main/java/com/example/PostRepository.java.

gavinking commented 11 months ago

@hantsy The reason that works out nicely in reactive is that every operation returns a Uni, so one single method definition can handle the case of Uni<Result> and Uni<Void>. But here we need the overload.