-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.html
580 lines (530 loc) · 30.9 KB
/
index.html
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
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
<!DOCTYPE html>
<html lang=en>
<head>
<meta charset=utf-8>
<meta http-equiv=X-UA-Compatible content="IE=edge">
<meta name=viewport content="width=device-width,initial-scale=1">
<meta name=description content="mjdbc - small and efficient JDBC wrapper">
<meta name=keywords content="jdbc, java, jdbi, mjdbc, sql, mapper, transaction, ORM">
<meta name=author content="Mikhail Fursov and mjdbc contributors">
<title>mJDBC - small and efficient JDBC wrapper</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" crossorigin="anonymous">
<link rel="stylesheet" href="site.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js"></script>
</head>
<body>
<div class="bs-docs-header" id="content" tabindex="-1">
<div class="container">
<div class="logo-header-block">
<div class="lang-switch-block"><a href="/" title="Switch to English">en</a> | <a href="/ru" title="Переключиться на русский">ru</a></div>
<h1 class="logo-header">mJDBC<sub>v1.3.1</sub></h1>
</div>
<div class="header-text">Small and efficient <a href="https://en.wikipedia.org/wiki/Java_Database_Connectivity" target="_blank">JDBC</a> wrapper
</div>
<div class="header-links-block">
<a href="http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22com.github.mjdbc%22%20AND%20a%3A%22mjdbc%22" class="btn btn-default btn-sm btn-header" target="_blank">Maven</a>
<a href="http://github.com/mjdbc/mjdbc" class="btn btn-default btn-sm btn-header" target="_blank">GitHub</a>
</div>
</div>
</div>
<div class="container bs-docs-main">
<div class="row">
<!--Main Content -->
<div class="col-xs-9">
<section id="About" class="group">
<h3>About</h3>
<ul class="feature-list">
<li><i>Small</i> - no external dependencies. Jar size is less than 50kb.</li>
<li><i>Simple</i> - no special configuration required: 1 line of code to start.</li>
<li><i>Reliable</i> - all SQL statements are parsed and validated during initialization.</li>
<li><i>Flexible</i> - switch and use native JDBC interface directly when needed.</li>
<li><i>Fast</i> - no runtime overhead when compared to JDBC.</li>
<li><i>Transactional</i> - wrap any method into transaction.</li>
<li><i>Optimized</i> - SQL connection is requested during first statement execution.</li>
<li><i>Extensible</i> - add new data types or override the way built-in types are handled.</li>
<li><i>Measurable</i> - profile timings for all SQL queries and transactions.</li>
<li><i>Open</i> - fork the original code and change it.</li>
</ul>
</section>
<section id="Install" class="group">
<h3>Installation</h3>
<div>
Add the following code to Maven project file:
<pre class="prettyprint">
<dependency>
<groupId>com.github.mjdbc</groupId>
<artifactId>mjdbc</artifactId>
<version>1.3.1</version>
</dependency></pre>
</div>
</section>
<section id="Examples" class="group">
<div id="InstallExample" class="subgroup">
<h3>Examples</h3>
Example 1: SQL queries
<pre class="prettyprint">
// Step 1: Create mJDBC adapter for java.sql.DataSource
java.sql.DataSource ds = ...;
Db db = DbFactory.wrap(ds);
// Step 2: Design SQL interface
public interface UserSql {
@Sql("INSERT INTO users(login) VALUES (:login)")
int insertUser(@BindBean User user);
@Sql("SELECT * FROM users WHERE login = :login")
User getUserByLogin(@Bind("login") String login);
}
// Step 3: Define rules to map SQL results to Java objects
db.registerMapper(User.class, r -> {
User user = new User();
user.id = r.getInt("id");
user.login = r.getString("login");
...
return user;
};)
// Step 4: Get implementation for SQL interface
UserSql userSql = db.attachSql(UserSql.class);
// Step 5: Use SQL interface to perform queries
User user = userSql.getUserByLogin("login");</pre>
Example 2: Transactions
<pre class="prettyprint">
// Step 1: Create an interface with transactional methods
public interface UserDbi {
void registerUser(User user);
}
// Step 2: Implement the interface
public class UserDbiImpl implements UserDbi {
public void registerUser(User user) {
User copy = userSql.getUserByLogin(user.login);
assertNull(copy, "User already exists: " + user.login);
user.id = userSql.insertUser(user);
}
}
// Step 3: Get proxy-adapter for the interface with transactions support
UserDbi userDbi = db.attachDbi(UserDbi.class, new UserDbiImpl());
// Step 4: Use the adapter
userDbi.registerUser(new User("root"));</pre>
</div>
</section>
<section id="Adapter" class="group">
<h3>mJDBC adapter</h3>
<p>
To start using mJDBC create an instance of <i>com.github.mjdbc.Db</i> providing <i>javax.sql.DataSource</i> object to the factory method:
</p>
<pre class="prettyprint">
static Db DbFactory.wrap(DataSource ds)</pre>
<p>
<a href="#Transactions">Transactional interfaces</a> allows to execute multiple SQL requests within a single transaction: either all
of SQL request inside transaction will succeed or no effect on database state will done at all.
</p>
<p>
Any Java interface can be made transactional. To register the interface as transactional use the following method:
</p>
<pre class="prettyprint">
<T> T attachDbi(T impl, Class<T> dbiInterface)</pre>
<p>
<a href="#Sql">SQL interfaces</a> - is a way to create maintainable set of SQL queries that checked for correctness during the interface registration.
SQL queries are written as <i>@Sql</i> annotations to methods and parameters are bound with <i>@Bind</i> and <i>@BindBean</i> classes.
When SQL interface is registered in mJDBC it returns a Proxy for the interface with SQL queries checked and implemented.
</p>
<pre class="prettyprint">
<T> T attachSql(Class<T> sqlInterface)</pre>
<p>
<a href="#Binders"></a>Set of supported SQL interface parameter types can be extended by custom Java types by creating and registering new <i>DbBinder<T></i> implementations,
which are responsible for Java objects mapping to parameters of <i>java.sql.PreparedStatement</i>
</p>
<pre class="prettyprint">
<T> void registerBinder(Class<? extends T> binderClass, DbBinder<T> binder)</pre>
<p>
<a href="#Mappers">Return values</a> for SQL interfaces are instantiated using corresponding <i>DbMapper<T></i> instances.
mJDBC supports by default primitive Java types, JDBC types and Java Lists. Support for custom return types can be added by using
implementing and registering new <i>DbMapper<T></i> instance using the following method:
</p>
<pre class="prettyprint">
<T> void registerMapper(Class<T> mapperClass, DbMapper<T> mapper)</pre>
<p>
mJDBC provides <a href="#LowLevelApi">low level API</a> to create and run queries without SQL or transactional interfaces still
utilising most of the benefits of mJDBC while having full access and control over JDBC objects.
</p>
<p>
<i>@Nullable</i> and <i>@NotNull</i> annotations are used throughout all API for strict control over <i>null</i> values.
Some API calls that may or may not return <i>null</i> are intentionally duplicated and users of the API are encouraged to follow null safety.
</p>
<pre class="prettyprint">
@Nullable
<T> T execute(@NotNull DbOp<T> op)
@NotNull
<T> T executeNN(@NotNull DbOpNN<T> op)
void executeV(@NotNull DbOpV op)</pre>
<p>
mJDBC automatically collects and provides simple <a href="#Profiling">profiling information</a> about
number of calls and total time spent in methods of SQL and transactional interfaces.
This information is available via <i>getTimers</i> method:
</p>
<pre class="prettyprint">
Map<Method, DbTimer> getTimers()</pre>
</section>
<section id="Transactions" class="group">
<h3>Transactions</h3>
mJDBC supports the following pattern for transactions:
<ul class="spec-list">
<li>A developer defines and implements some Java interface.</li>
<li>mJDBC provides proxy-implementation for the given interface to manage transactional context on each interface method call
and forward all calls to the original implementation.
</li>
<li>The developer should use the proxy implementation for the interface provided by mJDBC.</li>
</ul>
<p>
Every method of the interface is a separate transaction: <i>commit</i> for is called after successful method call, <i>rollback</i> in case
if exception was thrown.
</p>
<p>
No new transaction created if one transactional interface method is called from within another.
The method called becomes a part of the upper-level transaction.
</p>
<p>
Implementation of transactions in mJDBC works the way that the real transaction as well as SQL connection request from <i>java.sql.DataSource</i>
occurs not during a call of the proxy method, but only during execution of the first real SQL call.
This way the methods of transactional interface that do not run any operations over database: use cache or trigger exceptions on arguments check
are executed without any database related overhead.
</p>
<p>
Transactional interfaces are simple Java interfaces: mJDBC does not require extending marker interfaces or use special annotations.
To get proxy implementation for a transactional interface the interface and its implementation must be registered using the following mJDBC call:
</p>
<pre class="prettyprint">
@NotNull
<T> T attachDbi(@NotNull T impl, @NotNull Class<T> dbiInterface)</pre>
<p>The <i>dbi</i> prefix here stands for "database interface".</p>
<p> Examples of transactional interfaces:
<i>
<a href="https://github.com/mjdbc/mjdbc/blob/master/src/test/java/com/github/mjdbc/test/asset/dbi/SampleDbi.java" target="_blank" class="nw">SampleDbi</a>,
<a href="https://github.com/mjdbc/mjdbc/blob/master/src/test/java/com/github/mjdbc/test/asset/dbi/SampleDbiImpl.java" target="_blank" class="nw">SampleDbiImpl</a>,
<a href="https://github.com/mjdbc/mjdbc/blob/master/src/test/java/com/github/mjdbc/test/SamplesTest.java" target="_blank" class="nw">SamplesTest</a>.
</i>
</p>
</section>
<section id="Sql" class="group">
<h3>SQL interfaces</h3>
<p>
SQL interface is a Java interface with every method associated with a single SQL request.
mJDBC provides implementation for SQL interface methods and handles method parameters and results mappings.
</p>
<p>
To create new SQL interface:
</p>
<ul class="spec-list">
<li>Create usual Java interface. Each method will be associated with SQL request.</li>
<li>Add native SQL query as <i>@Sql</i> annotation for every method.</li>
<li>Bind Java method parameters to named SQL parameters using <i>@Bind</i> or <i>@BindBean</i> annotations.</li>
<li>Get the interface implementation from mJDBC and use it to execute SQL queries.</li>
</ul>
<p>
SQL interface example:
</p>
<pre class="prettyprint">
public interface UserSql {
@NotNull
@GetGeneratedKeys
@Sql("INSERT INTO users(login, first_name, last_name)
VALUES (:login, :firstName, :lastName)")
UserId insertUser(@BindBean User user);
@Nullable
@Sql("SELECT * FROM users WHERE id = :id")
User getUserById(@Bind("id") UserId id);
@Nullable
@Sql("SELECT * FROM users WHERE login = :login")
User getUserByLogin(@Bind("login") String login);
@Sql("SELECT COUNT(*) FROM users")
int countUsers();
}</pre>
<p>
To obtain SQL interface implementation use the following method:
</p>
<pre class="prettyprint">
@NotNull
<T> T attachSql(@NotNull Class <T> sqlInterface);
</pre>
<p>
During this method call mJDBC will parse and check that all SQL parameters used in the request are present
and types of parameters and return value are supported.
</p>
<p>
All SQL parameters are named and are bound to Java parameters by their names. All names are prefixed with ':' symbol in SQL.
</p>
<p>
<i>@Bind</i> annotation is used to bind SQL parameters to Java method parameters. The annotation holds a name for corresponding
parameter in SQL query. <i>@BindBean</i> annotation is an alternative for <i>@Bind</i>: if used all parameters are derived from annotated
Java object fields. These fields must be public or have a public <i>get</i> methods.
</p>
<p>
mJDBC creates a separate <i>java.sql.PreparedStatement</i> object for each SQL interface method.
To bind Java or standard JDBC parameter types mJDBC calls corresponding methods of PreparedStatement object.
In order to use custom data types as SQL parameters there is a special API to register parameter binder class instances:
<a href="#Binders"> <i>DbBinder</i></a>, or implement interface for special set of additional data types supported by mJDBC:
<a href="https://github.com/mjdbc/mjdbc/blob/master/src/main/java/com/github/mjdbc/type/DbInt.java" target="_blank" class="nw"><i>DbInt</i></a>,
<a href="https://github.com/mjdbc/mjdbc/blob/master/src/main/java/com/github/mjdbc/type/DbString.java" target="_blank" class="nw"><i>DbString</i></a> etc.
</p>
<p>
To enable support for custom non-Java or non-JDBC return type for SQL interface methods implement and register <a href="#Mappers"><i>DbMapper</i></a> class.
This class will be used by mJDBC to map a single <i>java.sql.ResultSet</i> row into an instance of user defined type.
Lists (<i>java.util.List</i>) and basic Java and JDBC types are supported by mJDBC by default.
</p>
<p>
To return auto-generated SQL value use <i>@GetGeneratedKeys</i> annotation for SQL method.
Use of <i>@GetGeneratedKeys</i> is optional for SQL statements that starts from "INSERT " prefix:
mJDBC will apply <i>@GetGeneratedKeys</i> to them automatically.
</p>
<p>
In case if Java parameter is iterator (<i>java.util.Iterator</i>),
collection (<i>java.util.Iterable</i>) or Java <i>array</i> instance mJDBC will use <a href="#Batch">batch mode</a> to execute the query.
</p>
</section>
<section id="Binders" class="group">
<h3>SQL parameters</h3>
<p>
To handle <a href="#Sql">SQL interface</a> parameters mJDBC uses <i>DbBinder</i> interface and <i>@Bind</i> / <i>@BindBean</i> annotations.
<i>DbBinder</i> interface defines the way Java type is converted to the real <i>java.sql.PreparedStatements</i> parameter:
</p>
<pre class="prettyprint">
public interface DbBinder<T> {
void bind(PreparedStatement statement, int idx, T value)
}</pre>
<p>When executing SQL query mJDBC automatically selects correct <i>DbBinder</i> from the set of registered binders.
The priority of <i>DbBinder</i> selection is the following:</p>
<ul class="spec-list">
<li>Same type as parameter type.</li>
<li>Same type as parameter parent type.</li>
<li>Same type with one of the parameter extended interfaces.</li>
</ul>
<p>
If more than one interface is found mJDBC will throw <i>java.lang.IllegalArgumentException.</i>
<i>DbBinder</i> are resolved for all parameters during SQL interface registration call.
</p>
<p>To register new <i>DbBinder</i> implementation use the following method</p>
<pre class="prettyprint">
<T> void registerBinder(Class<? extends T> binderClass, DbBinder<T> binder)</pre>
<p>
<i>@Bind</i> annotation used to specify a name of the annotated parameter as used in SQL request.
</p>
<p>
<i>@BindBean</i> annotation enforces mJDBC to bind all SQL parameter to public object field names or getter methods.
Today <i>@BindBean</i> parameter must be the only parameter of the method.
</p>
<p>
In case if SQL statement contains more named parameters than can be resolved from method parameters annotated with <i>@Bind</i> or <i>@BindBean</i>
an exception is thrown. Unused <i>@Bind</i> and <i>@BindBean</i> parameters are ignored. The names of parameters are validated to be valid Java identifiers.
</p>
<p>mJDBC verifies that all SQL statement parameters are correctly mapped is performed during SQL interface registration.</p>
</section>
<section id="Mappers" class="group">
<h3>SQL results</h3>
<p>
mJDBC must know how to correctly instantiate and initialize results of Sql interface methods.
Out of the box mJDBC supports all primitive Java type and their Object counterparts, <i>java.sql.Date</i>, <i>java.sql.Timestamp</i>, <i>java.util.Date</i>,
and <i>java.math.BigDecimal</i> types and <i>java.util.List</i> interface for the case when multiple results are returned.
</p>
<p>
To extend the set of supported method result type a new instance of <i>DbMapper</i> interface must be registered. This instance must provide a method that is used to map
any given <i>ResultSet</i> position into valid result object instance.
</p>
<pre class="prettyprint">
public interface DbMapper<T> {
T map(@NotNull java.sql.ResultSet r) throws SQLException;
}</pre>
<p>Example: </p>
<pre class="prettyprint">
DbMapper<User> mapper = (r) -> {
User user = new User();
user.id = new UserId(r.getInt("id"));
user.login = r.getString("login");
return user;
}
db.registerMapper(User.class, mapper);
</pre>
<p>
To make mJDBC automatically find <i>DbMapper</i> implementation for Sql interface results the following condition must be met for any given type <T>:
</p>
<ul class="spec-list">
<li>The class or return type has a static field annotated with <i>@Mapper</i> and with a type <i>DbMapper<T></i></li>
</ul>
<p>
The resolve algorithm described above is performed by mJDBC only if for the given type <T> there
is no manually registered <i>DbMapper<T></i> instance.
</p>
<p>
<i>DbMapper</i> instance resolution is performed during Sql interface registration.
If there are 2 or more candidates for the given type <T> mJDBC throws Exception and does not register Sql interface.</p>
<p>
Multiple <i>registerMapper</i> calls for the same type <T> are allowed and result to active <i>DbMapper</i> instance update.
</p>
</section>
<section id="Batch" class="group">
<h3>Batch operations</h3>
<p>
Batch operations are used to optimize a series of identical parametrized database updates. Example:
</p>
<pre class="prettyprint">
@Sql("UPDATE users SET score = :score WHERE id = :id")
void updateScore(@Bind("id") int[] ids, @Bind("score") int score);
@Sql("UPDATE users SET score = :score WHERE id = :id")
void updateScore(@BindBean List<User> users);
@Sql("INSERT INTO users(login, score) VALUES (:login, :score)")
void insertUsers(@BindBean List<User> users);</pre>
<p>
With batch operations mJDBC uses a single instance of <i>java.sql.PreparedStatement</i> object to
execute the whole series of updates and utilizes <i>addBatch/executeBatch</i> JDBC API.
</p>
<p>Count of <i>addBatch</i> methods invocations before <i>executeBatch</i> call can be set up by <i>batchChunkSize</i>
parameter of <i>@Sql</i> annotation. Default value for this parameter is <i>Integer.MAX_VALUE</i>.
It means that mJDBC will try to put all data into a single batch update by default.</p>
<pre class="prettyprint">
@Sql(value = "UPDATE users SET score = :score WHERE id = :id",
batchChunkSize = 100)
void updateScore(@BindBean List<User> users);
</pre>
<p>
mJDBC detects batch parameters by their types: the following Java types are considered as batch parameters:
Java arrays, <i>java.util.Iterable</i> and <i>java.util.Iterator</i>.
</p>
<p>
Batch parameters are mapped to native named SQL parameters like regular parameters with <i>@Bind</i> and <i>@BindBean</i> annotations.
The only restriction for batch parameters: only 1 batch parameter per <i>@SQL</i> query is allowed.
</p>
</section>
<section id="Profiling" class="group">
<h3>Profiling</h3>
mJDBC tracks total execution time and number of calls for registered SQL interfaces and transactional methods.
To access profiling information use:
<pre class="prettyprint">
@NotNull
Map<Method, DbTimer> getTimers();</pre>
where <i>DbTimer</i> is the following structure:
<pre class="prettyprint">
public final class DbTimer {
@NotNull
private final Method method;
protected volatile long invocationCount;
protected volatile long totalTimeInNanos;</pre>
</section>
<section id="LowLevelApi" class="group">
<h3>Low level API</h3>
<div class="subgroup">
<h4 id="DbOp">Transactions</h4>
<p>
mJDBC allows to declare transactional boundaries manually without use of transactional or SQL interfaces.
This option may be useful for small applications in order to avoid coding of interfaces or in case if transactional interfaces do
not provide features needed.
</p>
<p>
In order to run some code inside of SQL transaction and avoid transactional interfaces use one the the following mJDBC methods:
</p>
<pre class="prettyprint">
@Nullable
<T> T execute(@NotNull DbOp<T> op);
@NotNull
<T> T executeNN(@NotNull DbOpNN<T> op);
void executeV(@NotNull DbOpV op);</pre>
<p>When any of the methods above is called mJDBC will wrap the <i>DbOp</i> implementation into a real SQL transaction first and run
the implementation from within the transaction. The logic here is the same as with transactional interfaces: once the top-level method finishes successfully
the transaction commits. Transaction is rolled back if the method throws any exception. All nested method calls reuse existing transactional context. </p>
<pre class="prettyprint">
/**
* Database operation with @Nullable result.
*/
public interface DbOp<T> {
@Nullable
T run(@NotNull DbConnection c) throws Exception;
}
/**
* Database operation with no result.
*/
public interface DbOpV {
void run(@NotNull DbConnection c) throws Exception;
}
/**
* Database operation with @NotNull result.
*/
public interface DbOpNN<T> {
@NotNull
T run(@NotNull DbConnection c) throws Exception;
}</pre>
<p>mJDBC provides 3 similar DbOp interfaces that handles return values differently.
It allows to use more expressive syntax and utilize power of static code analyzers.</p>
<p><i>DbOp</i>'s <i>DbConnection</i> parameter provides to user direct access to <i>java.sql.Connection</i>
and is used by mJDBC together with <i>DbPreparedStatement</i> class described below.</p>
<p>If the top level <i>DbOp.run</i> method is finished normally without throwing an exception, active transaction is committed.
In case if there was an exception the transaction is rolled back.
Nested <i>execute(DbOp)</i> calls do not create new transactions and reuse transaction context from the caller method.</p>
</div>
<div class="subgroup">
<h4 id="DbStatement">SQL queries</h4>
<p>
To create SQL queries directly without use of SQL interfaces mJDBC provides <i>DbPreparedStatement</i> class.
This class is a wrapper and provides direct access to <i>java.sql.PreparedStatement</i> and the following additional functionality:
</p>
<ul class="spec-list">
<li>Support of named parameters.</li>
<li>Instantiation time parameters syntax validation.</li>
<li>Support for results mapping with <i>DbMapper</i> interface.</li>
<li>SQL resources cleanup (like open ResultSets) when leaving transaction boundaries.</li>
</ul>
<p>
Examples of <i>DbPreparedStatement</i> used with <i>DbOp</i>:
</p>
<pre class="prettyprint">
List<User> users = db.execute(c ->
new DbPreparedStatement<>(c, "SELECT * FROM users", User.class)
.queryList());</pre>
<pre class="prettyprint">
User user = db.execute(c ->
new DbPreparedStatement<>(c, "SELECT * FROM users WHERE login = :login", User.class).set("login", "admin").query());</pre>
</div>
<p>
All queries with <i>DbPreparedStatement</i> run inside another <i>DbOp</i> wrapper use the same transaction.
All SQL resources inside the transaction are tracked by mJDBC and automatically released when transaction is finised.</p>
</section>
<section id="Recommendations" class="group">
<h3>Recommendations</h3>
<ul class="spec-list">
<li>Use sample code from mJDBC tests:
<a href="https://github.com/mjdbc/mjdbc/tree/master/src/test/java/com/github/mjdbc/test" target="_blank">test cases</a>,
<a href="https://github.com/mfursov/wicket7template/tree/master/src/main/java/com/github/mfursov/w7/db" target="_blank">other projects</a> on GitHub.
</li>
<li>Use database connection pooling. Example: <a href="https://brettwooldridge.github.io/HikariCP/" target="_blank">HikariCP</a></li>
</ul>
</section>
</div>
<!--Nav Bar -->
<nav class="col-xs-3 bs-docs-sidebar">
<ul id="sidebar" class="nav nav-stacked fixed">
<li><a href="#About">About</a></li>
<li><a href="#Install">Installation</a></li>
<li><a href="#Examples">Examples</a></li>
<li><a href="#Adapter">mJDBC adapter</a></li>
<li><a href="#Transactions">Transactions</a></li>
<li><a href="#Sql">SQL interfaces</a></li>
<li><a href="#Binders">SQL parameters</a></li>
<li><a href="#Mappers">SQL results</a></li>
<li><a href="#Batch">Batch operations</a></li>
<li><a href="#Profiling">Profiling</a></li>
<li><a href="#LowLevelApi">Low level API</a>
<ul class="nav nav-stacked">
<li><a href="#DbOp">Transactions</a></li>
<li><a href="#DbStatement">SQL queries</a></li>
</ul>
</li>
<li><a href="#Recommendations">Recommendations</a></li>
</ul>
</nav>
</div>
</div>
<script>
$('body').scrollspy({
target: '.bs-docs-sidebar',
offset: 40
});
</script>
</body>
</html>