This repository has been archived by the owner on Nov 24, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 23
/
package.scala
299 lines (268 loc) · 12.2 KB
/
package.scala
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
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
package com.datasift.dropwizard.scala
import scala.reflect._
import org.skife.jdbi.v2._
import org.skife.jdbi.v2.sqlobject.mixins.Transactional
import org.skife.jdbi.v2.tweak.HandleCallback
/** Global definitions and implicits for JDBI. */
package object jdbi {
implicit final def JDBIWrapper(db: DBI) = new JDBIWrapper(db)
/** Provides idiomatic Scala enhancements to the JDBI API.
*
* Examples -
*
* dbi.open[DAO] to open a handle and attach a new sql object of the specified type to that handle
*
* dbi.daoFor[DAO] to create a new sql object which will obtain and release connections from this dbi instance,
* as it needs to, and can, respectively
*
* When in scope, you can create transactions using for comprehension. For instance -
* {{{
* for { handle <- dbi.transaction
* dao1 <- handle.attachable[Dao1]
* ...
* daoN <- handle.attachable[DaoN] } yield {
*
* dao1.some_function()
* ...
* daoN.some_other_function()
* }
* }}}
*
* @param db the [[org.skife.jdbi.v2.DBI]] instance to wrap.
*/
class JDBIWrapper private[jdbi](db: DBI) {
/** Creates a typed DAO instance.
*
* @tparam T type of the DAO to create.
* @return a DAO instance for the specified type.
*/
def open[T : ClassTag]: T = db.open[T](classTag[T].runtimeClass.asInstanceOf[Class[T]])
/** Creates an on-demand typed DAO instance.
*
* @tparam T type of the DAO to create.
* @return an on-demand DAO instance for the specified type.
*/
def daoFor[T : ClassTag]: T = db.onDemand[T](classTag[T].runtimeClass.asInstanceOf[Class[T]])
/** Executes the given function within a transaction.
*
* @tparam A the return type of the function to execute.
* @param f the function to execute within the transaction.
* @return the result of the function.
* @throws Exception if an Exception is thrown by the function, the transaction will be
* rolled-back.
*/
def inTransaction[A](f: (Handle, TransactionStatus) => A): A = {
db.inTransaction(new TransactionCallback[A] {
def inTransaction(handle: Handle, status: TransactionStatus): A = f(handle, status)
})
}
/** Executes the given function within a transaction.
*
* @tparam A the return type of the function to execute.
* @param f the function to execute within the transaction.
* @return the result of the function.
* @throws Exception if an Exception is thrown by the function, the transaction will be
* rolled-back.
*/
def inTransaction[A](f: Handle => A): A = {
db.inTransaction(new TransactionCallback[A] {
def inTransaction(handle: Handle, status: TransactionStatus): A = f(handle)
})
}
/** Executes the given function within a transaction of the given isolation level.
*
* @tparam A the return type of the function to execute.
* @param isolation the isolation level for the transaction.
* @param f the function to execute within the transaction.
* @return the result of the function.
* @throws Exception if an Exception is thrown by the function, the transaction will be
* rolled-back.
*/
def inTransaction[A](isolation: TransactionIsolationLevel)
(f: (Handle, TransactionStatus) => A): A = {
db.inTransaction(isolation, new TransactionCallback[A] {
def inTransaction(handle: Handle, status: TransactionStatus): A = f(handle, status)
})
}
/** Executes the given function within a transaction of the given isolation level.
*
* @tparam A the return type of the function to execute.
* @param isolation the isolation level for the transaction.
* @param f the function to execute within the transaction.
* @return the result of the function.
* @throws Exception if an Exception is thrown by the function, the transaction will be
* rolled-back.
*/
def inTransaction[A](isolation: TransactionIsolationLevel)
(f: Handle => A): A = {
db.inTransaction(isolation, new TransactionCallback[A] {
def inTransaction(handle: Handle, status: TransactionStatus): A = f(handle)
})
}
/** Applies the given function with a DBI [[org.skife.jdbi.v2.Handle]].
*
* @tparam A the return type of the function to apply.
* @param f the function to apply the handle to.
* @return the result of applying the function.
* @throws Exception if an Exception is thrown by the function.
*/
def withHandle[A](f: Handle => A): A = {
db.withHandle(new HandleCallback[A] {
def withHandle(handle: Handle): A = f(handle)
})
}
/** Extends this DBI to support for-comprehensions for transactions. */
def transaction: JDBITransactionWrapper =
new JDBITransactionWrapper(this)
}
/** Provides for-comprehension support for composable transactions */
class JDBITransactionWrapper private[jdbi] (dbi: JDBIWrapper) {
def map[A](f: Handle => A): A = dbi.inTransaction(f)
def flatMap[A](f: Handle => A): A = map(f)
def foreach(f: Handle => Unit): Unit = map(f)
}
implicit final def HandleWrapper(handle: Handle) = new HandleWrapper(handle)
/** Provides idiomatic Scala enhancements to the JDBI API.
*
* @param handle the [[org.skife.jdbi.v2.Handle]] instance to wrap.
*/
class HandleWrapper private[jdbi] (handle: Handle) {
/** Creates a typed DAO instance attached to this [[org.skife.jdbi.v2.Handle]].
*
* @tparam A type of the DAO to create.
* @return a DAO instance for the specified type.
*/
def attach[A : ClassTag]: A = {
handle.attach(classTag[A].runtimeClass.asInstanceOf[Class[A]])
}
/** Extends this [[org.skife.jdbi.v2.Handle]] to support the creation of typed DAOs through for-comprehensions. */
def attachable[A : ClassTag]: HandleDaoWrapper[A] =
new HandleDaoWrapper[A](handle, classTag[A].runtimeClass.asInstanceOf[Class[A]])
/** Executes the given function within a transaction.
*
* @tparam A the return type of the function to execute.
* @param f the function to execute within the transaction.
* @return the result of the function.
* @throws Exception if an Exception is thrown by the function, the transaction will be
* rolled-back.
*/
def inTransaction[A](f: Handle => A): A = {
handle.inTransaction(new TransactionCallback[A] {
def inTransaction(conn: Handle, status: TransactionStatus): A = f(conn)
})
}
/** Executes the given function within a transaction.
*
* @tparam A the return type of the function to execute.
* @param f the function to execute within the transaction.
* @return the result of the function.
* @throws Exception if an Exception is thrown by the function, the transaction will be
* rolled-back.
*/
def inTransaction[A](f: (Handle, TransactionStatus) => A): A = {
handle.inTransaction(new TransactionCallback[A] {
def inTransaction(conn: Handle, status: TransactionStatus): A = f(conn, status)
})
}
/** Executes the given function within a transaction.
*
* @tparam A the return type of the function to execute.
* @param isolation the isolation level for the transaction.
* @param f the function to execute within the transaction.
* @return the result of the function.
* @throws Exception if an Exception is thrown by the function, the transaction will be
* rolled-back.
*/
def inTransaction[A](isolation: TransactionIsolationLevel)
(f: Handle => A): A = {
handle.inTransaction(isolation, new TransactionCallback[A] {
def inTransaction(conn: Handle, status: TransactionStatus): A = f(conn)
})
}
/** Executes the given function within a transaction.
*
* @tparam A the return type of the function to execute.
* @param isolation the isolation level for the transaction.
* @param f the function to execute within the transaction.
* @return the result of the function.
* @throws Exception if an Exception is thrown by the function, the transaction will be
* rolled-back.
*/
def inTransaction[A](isolation: TransactionIsolationLevel)
(f: (Handle, TransactionStatus) => A): A = {
handle.inTransaction(isolation, new TransactionCallback[A] {
def inTransaction(conn: Handle, status: TransactionStatus): A = f(conn, status)
})
}
}
class HandleDaoWrapper[A] private [jdbi] (handle: Handle, clazz: Class[A]) {
//require(handle.isInTransaction, "handle must be in a transaction")
def map[B](f: A => B): B = f(handle.attach(clazz))
def flatMap[B](f: A => B): B = map(f)
def foreach(f: A => Unit): Unit = map(f)
}
implicit final def TransactionalWrapper[A <: Transactional[A]](transactional : A) =
new TransactionalWrapper[A](transactional)
/** Provides enhancements to the Dropwizard jDBI API for transactional DAOs.
*
* @param transactional the [[org.skife.jdbi.v2.sqlobject.mixins.Transactional]] object to wrap.
*/
class TransactionalWrapper[A <: Transactional[A]] private[jdbi] (transactional: A) {
/** Executes the given function within a transaction of the given isolation level.
*
* @tparam B the type of the result of the function being executed.
* @param isolation the isolation level for the transaction.
* @param f the function on this object to execute within the transaction.
* @return the result of the function being executed.
* @throws Exception if an Exception is thrown by the function, the transaction will be
* rolled-back.
*/
def inTransaction[B](isolation: TransactionIsolationLevel)
(f: A => B): B = {
transactional.inTransaction[B](isolation, new Transaction[B, A] {
def inTransaction(tx: A, status: TransactionStatus): B = f(tx)
})
}
/** Executes the given function within a transaction of the given isolation level.
*
* @tparam B the type of the result of the function being executed.
* @param isolation the isolation level for the transaction.
* @param f the function on this object to execute within the transaction.
* @return the result of the function being executed.
* @throws Exception if an Exception is thrown by the function, the transaction will be
* rolled-back.
*/
def inTransaction[B](isolation: TransactionIsolationLevel)
(f: (A, TransactionStatus) => B): B = {
transactional.inTransaction[B](isolation, new Transaction[B, A] {
def inTransaction(tx: A, status: TransactionStatus): B = f(tx, status)
})
}
/** Executes the given function within a transaction.
*
* @tparam B the type of the result of the function being executed.
* @param f the function on this object to execute within the transaction.
* @return the result of the function being executed.
* @throws Exception if an Exception is thrown by the function, the transaction will be
* rolled-back.
*/
def inTransaction[B](f: A => B): B = {
transactional.inTransaction[B](new Transaction[B, A] {
def inTransaction(tx: A, status: TransactionStatus): B = f(tx)
})
}
/** Executes the given function within a transaction.
*
* @tparam B the type of the result of the function being executed.
* @param f the function on this object to execute within the transaction.
* @return the result of the function being executed.
* @throws Exception if an Exception is thrown by the function, the transaction will be
* rolled-back.
*/
def inTransaction[B](f: (A, TransactionStatus) => B): B = {
transactional.inTransaction[B](new Transaction[B, A] {
def inTransaction(tx: A, status: TransactionStatus): B = f(tx, status)
})
}
}
}