-
Notifications
You must be signed in to change notification settings - Fork 32
Expand file tree
/
Copy pathindex.html
More file actions
197 lines (171 loc) · 5.51 KB
/
index.html
File metadata and controls
197 lines (171 loc) · 5.51 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
<html>
<head>
<title>Transactions | Ebean</title>
<meta name="layout" content="_layout2/base-docs.html"/>
<meta name="bread1" content="Transactions" href="/docs/transactions"/>
<#assign n0_docs="active">
<#assign n1_transactions="active">
<#assign n2_transactions="active">
</head>
<body>
<h2 id="transactional">@Transactional</h2>
<p>
Annotate methods with <code>@Transactional</code> and all database queries and changes
will occur in a single transaction.
</p>
<p>
The transaction will use the <a href="/docs/intro/database/#default">default database</a>,
be put into the "thread local scope" and will commit if the methods completes successfully.
</p>
<pre content="java">
@Transactional
public void process(OffsetDateTime startOffset) {
...
customer.save();
contact.save();
}
</pre>
<h2 id="current">Transaction.current()</h2>
<p>
Use <code>Transaction.current()</code> to return the current transaction from "thread local scope"
of the <a href="/docs/intro/database/#default">default database</a>.
</p>
<pre content="java">
@Transactional
public void process(OffsetDateTime startOffset) {
...
Transaction txn = Transaction.current();
...
}
</pre>
<p>
use <code>database.currentTransaction()</code> to return the current transaction for a given database
that is typically not the default database.
</p>
<pre content="java">
Database otherDb = DB.byName("other");
Transaction txn = otherDb.currentTransaction();
</pre>
<h2 id="beginTransaction">beginTransaction()</h2>
<p>
As an alternative to <em>@Transactional</em> we can use <code>beginTransaction()</code> to
start an explicit transaction. The transaction is put into the "thread local scope" and used
by any subsequent queries, save, delete etc.
</p>
<p>
We should use a <em>try with resources</em> block to ensure that the transaction is closed
if any error occurs in the block.
</p>
<pre content="java">
try (Transaction transaction = DB.beginTransaction()) {
// do stuff...
Customer customer = ...
customer.save();
Order order = ...
order.save();
transaction.commit();
}
</pre>
<h4 id="kotlinUse">Kotlin transaction.use { }</h4>
<p>
Kotlin <code>use</code> is used similarly to <em>try with resources</em> to ensure
the transaction is closed.
</p>
<pre content="kotlin">
DB.beginTransaction().use { transaction ->
// do stuff...
val customer = ...
customer.save();
val order = ...
order.save();
transaction.commit()
}
</pre>
<h2 id="end">commit(), rollback(), end()</h2>
<p>
Often with a <em>try with resources</em> block we don't need explicit calls to
<code>transaction.rollback()</code> or <code>transaction.end()</code> like the
example for <a href="#beginTransaction">beginTransaction()</a> above.
</p>
<p>
<code>rollback()</code> will rollback the transaction and commonly we use that
in a catch block.
</p>
<p>
<code>end()</code> will rollback the transaction if it has not already been committed.
We primarily use <code>end()</code> in a finally block.
</p>
<pre content="java">
Transaction transaction = DB.beginTransaction()
try {
// do stuff...
Customer customer = ...
customer.save();
Order order = ...
order.save();
transaction.commit();
} catch (SomeException e) {
transaction.rollback();
} finally {
transaction.end(); // rollback if not committed
}
</pre>
<h2 id="commitAndContinue">commitAndContinue()</h2>
<p>
Occasionally in larger transactions we get to a point where we would like
to commit the changes to this point but then carry on processing with
subsequent changes potentially failing.
We use <code>transaction.commitAndContinue()</code> for this.
</p>
<h2 id="setRollbackOnly">setRollbackOnly()</h2>
<p>
We use <code>transaction.setRollbackOnly()</code> such that a transaction
will not commit but only rollback.
</p>
<p>
We can make use of this when some processing has a sort of "preview" mode where
we process changes but then do not commit. This can also be useful in some
testing scenarios.
</p>
<h2 id="createTransaction">createTransaction()</h2>
<p>
<code>database.createTransaction()</code> will create a transaction but it will
<em>NOT</em> be put in "thread local scope". We generally use this when we have
a transaction that we want to pass between threads.
</p>
<p>
For example: start a transaction, obtain a row lock, if that is successful pass the
transaction to a task to execute via a background thread.
</p>
<p>
When we use <code>createTransaction()</code> we must explicitly use the transaction
in queries and saving etc. We explicitly specify the transaction with query beans
via ... and <em>model.save(transaction)</em> etc.
</p>
<pre content="java">
try (Transaction transaction = DB.getDefault().createTransaction()) {
...
var customer = new QCustomer(transaction) // explicit transaction
.name.eq("Rob")
.findOne();
...
customer.update(transaction); // explicit transaction
}
</pre>
<h2 id="implicit">Implicit transactions</h2>
<p>
When no transactions are specified explicitly Ebean will create a transaction to perform the action.
</p>
<h4>Query - read only transaction</h4>
<p>
For queries Ebean will look to use a read only transaction. If a <code>Read Only DataSource</code> has
be configured Ebean will look to use that by default.
</p>
<h4>Insert, Update, Delete</h4>
<p>
For all persist requests like save, insert, update, delete Ebean will create a transaction and perform
a <code>COMMIT</code> at the end of the operation.
</p>
<@next_edit "Batch" "/docs/transactions/batch" "/docs/transactions/index.html"/>
</body>
</html>