Description
#51244 will disallow usage of Hibernate outside of transactions by default, for safety reasons and to guide users towards best practices.
At the same time, if there are advanced use cases that might justify not using a transaction (for performance, to avoid two DB round-trips) and that are safe, we should make sure to provide a way to selectively disable our safe default. Otherwise, people with a single endpoint where no transaction is needed might end up disabling the transaction requirement across their whole application.
The only use case I can imagine at the moment is any use of Hibernate (or raw JDBC) that implies a single SQL statement:
- If you execute a single statement, the DB should make it ACID; in particular the statement will "see" the data in a consistent, isolated state, and, in case of updates, should be atomic.
- If you execute two statements, each will have these properties, but another transaction could happen in-between, so consistency/isolation is an issue (first statement may not see the same data as the second statement) and, in case of updates, so is atomicity (the first statement may succeed while the second one fails).
Note this excludes things like StatelessSession#insertMultiple, which unfortunately relies on multiple statements in a single JDBC batch.
It does however likely cover a great many implementations of GET rest endpoints, assuming they correctly fetch all data in a single query (e.g. using fetch join) and use appropriate fetch strategies for to-many associations (or don't need to fetch any to-many).
Implementation ideas
Could we introduce some way for the developer to declare "this operation is expected to only run a single statement in DB, so feel free to skip the actual transaction if necessary"?
E.g.:
// Returns entity types directly, assuming the use of jackson-datatype-hibernate
@Transactional
public class MyRestResource {
@GET
@Atomic // NEW, name TBD
public Optional<MyEntity> get(Long id) {
return MyEntity.repo().find(id); // Single select statement
}
}
Then we could:
- Use the datasource in autocommit mode (no transaction)
- Handle the
@Transactional annotation as a check that:
- Only one "transactional resource" (in this case, datasource) is involved.
- Only a single statement is executed on that datasource.
- No transaction-affecting operation (suspending a transaction, calling a non-
@Atomic @Transactional method, ...) is executed.
The main thing I'm unsure of is how to handle this on the Narayana side. Can we temporarily set up the transaction manager so that it refuses to start a transaction when asked?
cc @mmusgrov @barreiro @gastaldi @Sanne @FroMage WDYT?
Description
#51244 will disallow usage of Hibernate outside of transactions by default, for safety reasons and to guide users towards best practices.
At the same time, if there are advanced use cases that might justify not using a transaction (for performance, to avoid two DB round-trips) and that are safe, we should make sure to provide a way to selectively disable our safe default. Otherwise, people with a single endpoint where no transaction is needed might end up disabling the transaction requirement across their whole application.
The only use case I can imagine at the moment is any use of Hibernate (or raw JDBC) that implies a single SQL statement:
Note this excludes things like
StatelessSession#insertMultiple, which unfortunately relies on multiple statements in a single JDBC batch.It does however likely cover a great many implementations of
GETrest endpoints, assuming they correctly fetch all data in a single query (e.g. usingfetchjoin) and use appropriate fetch strategies for to-many associations (or don't need to fetch anyto-many).Implementation ideas
Could we introduce some way for the developer to declare "this operation is expected to only run a single statement in DB, so feel free to skip the actual transaction if necessary"?
E.g.:
Then we could:
@Transactionalannotation as a check that:@Atomic@Transactionalmethod, ...) is executed.The main thing I'm unsure of is how to handle this on the Narayana side. Can we temporarily set up the transaction manager so that it refuses to start a transaction when asked?
cc @mmusgrov @barreiro @gastaldi @Sanne @FroMage WDYT?