/** * Execute given operation within a transaction and return a result. A {@link Transaction} reference is provided to * perform <code>commit</code> and <code>rollback</code> operations. * @param <R> Operation result type * @param operation Operation to execute (not null) * @return The operation result */ default <R> R withTransaction(TransactionalOperation<R> operation) { return withTransaction(operation, TransactionConfiguration.getDefault()); }
public void transactional4() throws IOException { // tag::transactional4[] getDatastore().requireTransactional().withTransaction(tx -> { // ... }, TransactionConfiguration.withAutoCommit()); // <1> // end::transactional4[] }
/** * Get the transaction isolation level according to given {@link TransactionConfiguration}. * @param transactionConfiguration transaction configuration * @return Optional isolation level */ private static Optional<Integer> getIsolationLevel(TransactionConfiguration transactionConfiguration) { if (transactionConfiguration == null) { return Optional.empty(); } return transactionConfiguration.getTransactionOptions().filter(o -> o instanceof JdbcTransactionOptions) .map(o -> (JdbcTransactionOptions) o).flatMap(o -> o.getTransactionIsolation()).map(i -> { switch (i) { case NONE: return TransactionDefinition.ISOLATION_DEFAULT; case READ_COMMITTED: return TransactionDefinition.ISOLATION_READ_COMMITTED; case READ_UNCOMMITTED: return TransactionDefinition.ISOLATION_READ_UNCOMMITTED; case REPEATABLE_READ: return TransactionDefinition.ISOLATION_REPEATABLE_READ; case SERIALIZABLE: return TransactionDefinition.ISOLATION_SERIALIZABLE; default: break; } return null; }); }
@Override public CompletionStage<Void> end() throws TransactionException { // check active if (!isActive()) { throw new IllegalTransactionStatusException("The transaction is not active"); } // check completed if (!isCompleted()) { if (isRollbackOnly()) { return rollback(); } else { if (getConfiguration().isAutoCommit()) { return commit().thenApply(r -> null); } } } LOGGER.debug(() -> "MongoDB transaction [" + this + "] finalized"); return CompletableFuture.completedFuture(null); }
@Override public <R> R withTransaction(TransactionalOperation<R> operation, TransactionConfiguration transactionConfiguration) { ObjectUtils.argumentNotNull(operation, "TransactionalOperation must be not null"); // check active transaction or create a new one final SyncMongoTransaction tx = getCurrentTransaction().map(t -> SyncMongoTransaction.delegate(t)) .orElseGet(() -> startTransaction(transactionConfiguration)); try { // execute operation return operation.execute(tx); } catch (Exception e) { // check rollback transaction if (tx.getConfiguration().isRollbackOnError() && !tx.isCompleted()) { tx.setRollbackOnly(); } throw e; } finally { try { endTransaction(tx); } catch (Exception e) { throw new DataAccessException("Failed to finalize transaction", e); } } }
public void transactional5() throws IOException { // tag::transactional5[] getDatastore().requireTransactional().withTransaction(tx -> { // ... }, TransactionConfiguration.create(false, false)); // <1> // end::transactional5[] }
/** * Finalize the transaction. * @throws TransactionException If an error occurred */ protected void endTransaction() throws TransactionException { getTransactionStatus().ifPresent(tx -> { if (!tx.isCompleted()) { try { if (isRollbackOnly()) { getTransactionManager().rollback(tx); } else { if (getConfiguration().isAutoCommit()) { getTransactionManager().commit(tx); } } } catch (Exception e) { throw new TransactionException("Failed to finalize transaction", e); } } }); }
@Override public <R> CompletionStage<R> withTransaction(AsyncTransactionalOperation<R> operation, TransactionConfiguration transactionConfiguration) { ObjectUtils.argumentNotNull(operation, "TransactionalOperation must be not null"); // check active transaction or create a new one return getCurrentTransaction() .map(t -> (CompletionStage<AsyncMongoTransaction>) CompletableFuture .completedFuture(AsyncMongoTransaction.delegate(t))) .orElseGet(() -> startTransaction(transactionConfiguration)).thenCompose(tx -> { // execute operation try { return operation.execute(tx).thenApply(r -> new TransactionalOperationResult<>(tx, r)); } catch (Exception e) { // check rollback transaction if (tx.getConfiguration().isRollbackOnError() && !tx.isCompleted()) { tx.setRollbackOnly(); } return CompletableFuture.completedFuture(new TransactionalOperationResult<R>(tx, e)); } }).thenApply(result -> { // finalize transaction endTransaction(result.getTransaction()); // check execution error if (result.getError() != null) { throw new TransactionException("Failed to execute operation", result.getError()); } // return the result return result.getResult(); }); }
/** * Execute given operation within a transaction and return a result. An {@link ReactiveTransaction} reference is * provided to perform <code>commit</code> and <code>rollback</code> operations. * @param <R> Operation result type * @param operation Operation to execute (not null) * @return A {@link Flux} which can be used to handle the asynchronous operation outcome and the operation results */ default <R> Flux<R> withTransaction(ReactiveTransactionalOperation<R> operation) { return withTransaction(operation, TransactionConfiguration.getDefault()); }
public void transactional() { // tag::transactional[] final Datastore datastore = getDatastore(); // build or obtain a JDBC Datastore datastore.requireTransactional().withTransaction(tx -> { // <1> PropertyBox value = buildPropertyBoxValue(); datastore.save(TARGET, value); tx.commit(); // <2> }); OperationResult result = datastore.requireTransactional().withTransaction(tx -> { // <3> PropertyBox value = buildPropertyBoxValue(); return datastore.save(TARGET, value); }, TransactionConfiguration.withAutoCommit()); // <4> // end::transactional[] }
@Override public void end() throws TransactionException { // check active if (!isActive()) { throw new IllegalTransactionStatusException("The transaction is not active"); } // check completed if (!isCompleted()) { if (isRollbackOnly()) { rollback(); } else { if (getConfiguration().isAutoCommit()) { commit(); } } } LOGGER.debug(() -> "MongoDB transaction [" + this + "] finalized"); }
/** * Get the MongoDB {@link TransactionOptions} using current transaction configuration. * @return The transaction options */ protected TransactionOptions getTransactionOptions() { final Optional<MongoTransactionOptions> txOptions = getConfiguration().getTransactionOptions() .filter(o -> o instanceof MongoTransactionOptions).map(o -> (MongoTransactionOptions) o); final TransactionOptions.Builder transactionOptions = TransactionOptions.builder(); txOptions.flatMap(o -> o.getReadConcern()).ifPresent(rc -> transactionOptions.readConcern(rc.getReadConcern())); txOptions.flatMap(o -> o.getWriteConcern()).flatMap(wc -> wc.getWriteConcern()) .ifPresent(wc -> transactionOptions.writeConcern(wc)); txOptions.flatMap(o -> o.getReadPreference()).flatMap(rp -> rp.getReadPreference()) .ifPresent(rp -> transactionOptions.readPreference(rp)); return transactionOptions.build(); }
/** * Execute given operation within a transaction and return a result. An {@link AsyncTransaction} reference is * provided to perform <code>commit</code> and <code>rollback</code> operations. * @param <R> Operation result type * @param operation Operation to execute (not null) * @return A {@link CompletionStage} which can be used to handle the asynchronous operation outcome and the * operation result */ default <R> CompletionStage<R> withTransaction(AsyncTransactionalOperation<R> operation) { return withTransaction(operation, TransactionConfiguration.getDefault()); }
public void transactional() { // tag::transactional[] final Datastore datastore = getJpaDatastore(); // build or obtain a JPA Datastore datastore.requireTransactional().withTransaction(tx -> { // <1> PropertyBox value = buildPropertyBoxValue(); datastore.save(TARGET, value); tx.commit(); // <2> }); OperationResult result = datastore.requireTransactional().withTransaction(tx -> { // <3> PropertyBox value = buildPropertyBoxValue(); return datastore.save(TARGET, value); }, TransactionConfiguration.withAutoCommit()); // <4> // end::transactional[] }
: TransactionConfiguration.getDefault();
: TransactionConfiguration.getDefault();