View Javadoc

1   package com.atlassian.sal.api.rdbms;
2   
3   import com.atlassian.annotations.PublicApi;
4   
5   import javax.annotation.Nonnull;
6   
7   /**
8    * Interface allowing the user to execute a callback with a {@link java.sql.Connection}, in the context of a transaction.
9    * <p/>
10   * Note that participation in an existing transaction i.e. <code>requiresNew</code> not set is merely a hint to the
11   * host application and not binding. Best effort will be attempted.
12   * <p/>
13   * The following example will query an application's table using JDBC:
14   * <pre>
15   * {@code
16   * final TransactionalExecutor transactionalExecutor = transactionalExecutorFactory
17   *         .createExecutor()
18   *         .readOnly()
19   *         .newTransaction();
20   *
21   * final String summary = transactionalExecutor.execute(new ConnectionCallback<String>()
22   * {
23   *     public String execute(final Connection connection)
24   *     {
25   *         try
26   *         {
27   *             final PreparedStatement preparedStatement = connection.prepareStatement(""
28   *                     + "select summary\n"
29   *                     + "from jiraissue\n"
30   *                     + "order by id desc");
31   *
32   *             final ResultSet resultSet = preparedStatement.executeQuery();
33   *
34   *             return resultSet.next() ? resultSet.getString("summary") : "no issues";
35   *         }
36   *         catch (SQLException e)
37   *         {
38   *             throw new RuntimeException("oh noes!", e);
39   *         }
40   *     }
41   * });
42   * }
43   * </pre>
44   *
45   * @see com.atlassian.sal.api.rdbms.TransactionalExecutorFactory
46   * @since 3.0
47   */
48  @PublicApi
49  public interface TransactionalExecutor {
50      /**
51       * Execute a callback which is supplied a {@link java.sql.Connection}, within a transaction.
52       * <p/>
53       * After successful execution, the transaction will be committed. If the transaction is within the scope of a larger
54       * transaction i.e. <code>requiresNew</code> has been set, it will be scheduled for commit, pending successful
55       * completion of the target transaction.
56       * <p/>
57       * If any exception is thrown by <code>callback</code>, the transaction will be immediately rolled back.
58       * <p/>
59       * Do not attempt to retain or reuse the Connection outside of the scope of <code>callback</code> or within a
60       * different thread. Connection is usually not considered thread safe.
61       * <p/>
62       * A {@link java.lang.UnsupportedOperationException} will be thrown on invoking any of the following:
63       * <ul>
64       * <li>{@link java.sql.Connection#setAutoCommit(boolean)}</li>
65       * <li>{@link java.sql.Connection#commit()}</li>
66       * <li>{@link java.sql.Connection#close()}</li>
67       * <li>{@link java.sql.Connection#rollback()}</li>
68       * <li>{@link java.sql.Connection#setReadOnly(boolean)}</li>
69       * <li>{@link java.sql.Connection#setReadOnly(boolean)}</li>
70       * <li>{@link java.sql.Connection#abort(java.util.concurrent.Executor)}</li>
71       * <li>{@link java.sql.Connection#setCatalog(String)}</li>
72       * <li>{@link java.sql.Connection#setSchema(String)}</li>
73       * <li>{@link java.sql.Connection#setTransactionIsolation(int)}</li>
74       * <li>{@link java.sql.Connection#setNetworkTimeout(java.util.concurrent.Executor, int)}</li>
75       * </ul>
76       *
77       * @param callback mandatory, may return {@link java.lang.Void}
78       * @return return value of <code>callback</code>
79       */
80      <A> A execute(@Nonnull ConnectionCallback<A> callback);
81  
82      /**
83       * Alter this executor so that the connection is read-only
84       *
85       * @return this executor
86       */
87      @Nonnull
88      TransactionalExecutor readOnly();
89  
90      /**
91       * Alter this executor so that the connection is read-write
92       *
93       * @return this executor
94       */
95      @Nonnull
96      TransactionalExecutor readWrite();
97  
98      /**
99       * Alter this executor so that it executes in a new transaction, regardless of any existing
100      *
101      * @return this executor
102      */
103     @Nonnull
104     TransactionalExecutor newTransaction();
105 
106     /**
107      * Alter this executor so that the connection executes within an existing transaction or creates a new one if one is
108      * not present
109      *
110      * @return this executor
111      */
112     @Nonnull
113     TransactionalExecutor existingTransaction();
114 }