-
Notifications
You must be signed in to change notification settings - Fork 12.9k
/
Copy pathconfiguration.html
1111 lines (1033 loc) · 61.4 KB
/
configuration.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
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html>
<!--
| Generated by Apache Maven Doxia Site Renderer 2.0.0 from src/site/markdown/configuration.md at 02 Jan 2025
| Rendered using Apache Maven Fluido Skin 2.0.1
-->
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="generator" content="Apache Maven Doxia Site Renderer 2.0.0" />
<meta name="author" content="Clinton Begin" />
<title>MyBatis 3 | Configuration – mybatis</title>
<link rel="stylesheet" href="./css/apache-maven-fluido-2.0.1.min.css" />
<link rel="stylesheet" href="./css/site.css" />
<link rel="stylesheet" href="./css/print.css" media="print" />
<script src="./js/apache-maven-fluido-2.0.1.min.js"></script>
</head>
<body>
<div class="container-fluid container-fluid-top">
<header>
<div id="banner">
<div class="pull-left"></div>
<div class="pull-right"><div id="bannerRight"><h1><a href="https://blog.mybatis.org/"><img class="class java.lang.Object" src="../images/mybatis-logo.png" alt="MyBatis logo" /> MyBatis</a></h1></div></div>
<div class="clear"><hr/></div>
</div>
<div id="breadcrumbs">
<ul class="breadcrumb">
<li id="publishDate">Last Published: 02 Jan 2025<span class="divider">|</span>
</li>
<li id="projectVersion">Version: 3.5.19</li>
</ul>
</div>
</header>
<div class="row-fluid">
<header id="leftColumn" class="span2">
<nav class="well sidebar-nav">
<ul class="nav nav-list">
<li class="nav-header">Reference Documentation</li>
<li><a href="index.html">Introduction</a></li>
<li><a href="getting-started.html">Getting Started</a></li>
<li class="active"><a><span class="icon-chevron-down"></span>Configuration XML</a>
<ul class="nav nav-list">
<li><a href="configuration.html#properties">properties</a></li>
<li><a href="configuration.html#settings">settings</a></li>
<li><a href="configuration.html#typealiases">typeAliases</a></li>
<li><a href="configuration.html#typehandlers">typeHandlers</a></li>
<li><a href="configuration.html#objectfactory">objectFactory</a></li>
<li><a href="configuration.html#plugins">plugins</a></li>
<li><a href="configuration.html#environments">environments</a></li>
<li><a href="configuration.html#databaseidprovider">databaseIdProvider</a></li>
<li><a href="configuration.html#mappers">mappers</a></li>
</ul></li>
<li><a href="sqlmap-xml.html"><span class="icon-chevron-right"></span>Mapper XML Files</a></li>
<li><a href="dynamic-sql.html">Dynamic SQL</a></li>
<li><a href="java-api.html"><span class="icon-chevron-right"></span>Java API</a></li>
<li><a href="statement-builders.html">SQL Builder Class</a></li>
<li><a href="logging.html">Logging</a></li>
<li class="nav-header">Project Documentation</li>
<li><a href="project-info.html"><span class="icon-chevron-right"></span>Project Information</a></li>
<li><a href="project-reports.html"><span class="icon-chevron-right"></span>Project Reports</a></li>
</ul>
</nav>
<div class="well sidebar-nav">
<div id="poweredBy">
<div class="clear"></div>
<div class="clear"></div>
<a href="https://maven.apache.org/" class="builtBy" target="_blank"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
</div>
</div>
</header>
<main id="bodyColumn" class="span10">
<section><a id="Avoid_blank_site"></a>
<h1 class="d-none">Avoid blank site</h1>
<section><a id="Configuration"></a>
<h2>Configuration</h2>
<p>The MyBatis configuration contains settings and properties that have a dramatic effect on how MyBatis behaves. The high level structure of the document is as follows:</p>
<ul>
<li>configuration
<ul>
<li><a href="#properties">properties</a></li>
<li><a href="#settings">settings</a></li>
<li><a href="#typeAliases">typeAliases</a></li>
<li><a href="#typeHandlers">typeHandlers</a></li>
<li><a href="#objectFactory">objectFactory</a></li>
<li><a href="#plugins">plugins</a></li>
<li><a href="#environments">environments</a>
<ul>
<li>environment
<ul>
<li>transactionManager</li>
<li>dataSource</li>
</ul></li>
</ul></li>
<li><a href="#databaseIdProvider">databaseIdProvider</a></li>
<li><a href="#mappers">mappers</a></li>
</ul></li>
</ul><section><a id="properties"></a>
<h3>properties</h3>
<p>These are externalizable, substitutable properties that can be configured in a typical Java Properties file instance, or passed in through sub-elements of the properties element. For example:</p>
<pre class="prettyprint"><code class="language-xml"><properties resource="org/mybatis/example/config.properties">
<property name="username" value="dev_user"/>
<property name="password" value="F2Fa3!33TYyg"/>
</properties>
</code></pre>
<p>The properties can then be used throughout the configuration files to substitute values that need to be dynamically configured. For example:</p>
<pre class="prettyprint"><code class="language-xml"><dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</code></pre>
<p>The username and password in this example will be replaced by the values set in the properties elements. The driver and url properties would be replaced with values contained from the config.properties file. This provides a lot of options for configuration.</p>
<p>Properties can also be passed into the SqlSessionFactoryBuilder.build() methods. For example:</p>
<pre class="prettyprint"><code class="language-java">SqlSessionFactory factory =
sqlSessionFactoryBuilder.build(reader, props);
// ... or ...
SqlSessionFactory factory =
new SqlSessionFactoryBuilder.build(reader, environment, props);
</code></pre>
<p>If a property exists in more than one of these places, MyBatis loads them in the following order:</p>
<ul>
<li>Properties specified in the body of the properties element are read first,</li>
<li>Properties loaded from the classpath resource or url attributes of the properties element are read second, and override any duplicate properties already specified,</li>
<li>Properties passed as a method parameter are read last, and override any duplicate properties that may have been loaded from the properties body and the resource/url attributes.</li>
</ul>
<p>Thus, the highest priority properties are those passed in as a method parameter, followed by resource/url attributes and finally the properties specified in the body of the properties element.</p>
<p>Since the MyBatis 3.4.2, your can specify a default value into placeholder as follow:</p>
<pre class="prettyprint"><code class="language-xml"><dataSource type="POOLED">
<!-- ... -->
<property name="username" value="${username:ut_user}"/> <!-- If 'username' property not present, username become 'ut_user' -->
</dataSource>
</code></pre>
<p>This feature is disabled by default. If you specify a default value into placeholder, you should enable this feature by adding a special property as follow:</p>
<pre class="prettyprint"><code class="language-xml"><properties resource="org/mybatis/example/config.properties">
<!-- ... -->
<property name="org.apache.ibatis.parsing.PropertyParser.enable-default-value" value="true"/> <!-- Enable this feature -->
</properties>
</code></pre>
<p><span class="label important">NOTE</span> This will conflict with the <code>":"</code> character in property keys (e.g. <code>db:username</code>) or the ternary operator of OGNL expressions (e.g. <code>${tableName != null ? tableName : 'global_constants'}</code>) on a SQL definition. If you use either and want default property values, you must change the default value separator by adding this special property:</p>
<pre class="prettyprint"><code class="language-xml"><properties resource="org/mybatis/example/config.properties">
<!-- ... -->
<property name="org.apache.ibatis.parsing.PropertyParser.default-value-separator" value="?:"/> <!-- Change default value of separator -->
</properties>
</code></pre>
<pre class="prettyprint"><code class="language-xml"><dataSource type="POOLED">
<!-- ... -->
<property name="username" value="${db:username?:ut_user}"/>
</dataSource>
</code></pre></section><section><a id="settings"></a>
<h3>settings</h3>
<p>These are extremely important tweaks that modify the way that MyBatis behaves at runtime. The following table describes the settings, their meanings and their default values.</p>
<table class="table table-striped">
<thead>
<tr class="a">
<th>Setting</th>
<th>Description</th>
<th>Valid Values</th>
<th>Default</th></tr></thead><tbody>
<tr class="b">
<td>cacheEnabled</td>
<td>Globally enables or disables any caches configured in any mapper under this configuration.</td>
<td>true | false</td>
<td>true</td></tr>
<tr class="a">
<td>lazyLoadingEnabled</td>
<td>Globally enables or disables lazy loading. When enabled, all relations will be lazily loaded. This value can be superseded for a specific relation by using the <code>fetchType</code> attribute on it.</td>
<td>true | false</td>
<td>false</td></tr>
<tr class="b">
<td>aggressiveLazyLoading</td>
<td>When enabled, any method call will load all the lazy properties of the object. Otherwise, each property is loaded on demand (see also <code>lazyLoadTriggerMethods</code>).</td>
<td>true | false</td>
<td>false (true in ≤3.4.1)</td></tr>
<tr class="a">
<td><del>multipleResultSetsEnabled</del></td>
<td>Deprecated. This option has no effect.</td>
<td>true | false</td>
<td>true</td></tr>
<tr class="b">
<td>useColumnLabel</td>
<td>Uses the column label instead of the column name. Different drivers behave differently in this respect. Refer to the driver documentation, or test out both modes to determine how your driver behaves.</td>
<td>true | false</td>
<td>true</td></tr>
<tr class="a">
<td>useGeneratedKeys</td>
<td>Allows JDBC support for generated keys. A compatible driver is required. This setting forces generated keys to be used if set to true, as some drivers deny compatibility but still work (e.g. Derby).</td>
<td>true | false</td>
<td>False</td></tr>
<tr class="b">
<td>autoMappingBehavior</td>
<td>Specifies if and how MyBatis should automatically map columns to fields/properties. NONE disables auto-mapping. PARTIAL will only auto-map results with no nested result mappings defined inside. FULL will auto-map result mappings of any complexity (containing nested or otherwise).</td>
<td>NONE, PARTIAL, FULL</td>
<td>PARTIAL</td></tr>
<tr class="a">
<td>autoMappingUnknownColumnBehavior</td>
<td>Specify the behavior when detects an unknown column (or unknown property type) of automatic mapping target.
<ul>
<li><code>NONE</code>: Do nothing</li>
<li><code>WARNING</code>: Output warning log (The log level of <code>'org.apache.ibatis.session.AutoMappingUnknownColumnBehavior'</code> must be set to <code>WARN</code>)</li>
<li><code>FAILING</code>: Fail mapping (Throw <code>SqlSessionException</code>)</li></ul>Note that there could be false-positives when <code>autoMappingBehavior</code> is set to <code>FULL</code>.</td>
<td>NONE, WARNING, FAILING</td>
<td>NONE</td></tr>
<tr class="b">
<td>defaultExecutorType</td>
<td>Configures the default executor. SIMPLE executor does nothing special. REUSE executor reuses prepared statements. BATCH executor reuses statements and batches updates.</td>
<td>SIMPLE REUSE BATCH</td>
<td>SIMPLE</td></tr>
<tr class="a">
<td>defaultStatementTimeout</td>
<td>Sets the number of seconds the driver will wait for a response from the database.</td>
<td>Any positive integer</td>
<td>Not Set (null)</td></tr>
<tr class="b">
<td>defaultFetchSize</td>
<td>Sets the driver a hint as to control fetching size for return results. This parameter value can be override by a query setting.</td>
<td>Any positive integer</td>
<td>Not Set (null)</td></tr>
<tr class="a">
<td>defaultResultSetType</td>
<td>Specifies a scroll strategy when omit it per statement settings. (Since: 3.5.2)</td>
<td>FORWARD_ONLY | SCROLL_SENSITIVE | SCROLL_INSENSITIVE | DEFAULT(same behavior with ‘Not Set’)</td>
<td>Not Set (null)</td></tr>
<tr class="b">
<td>safeRowBoundsEnabled</td>
<td>Allows using RowBounds on nested statements. If allow, set the false.</td>
<td>true | false</td>
<td>False</td></tr>
<tr class="a">
<td>safeResultHandlerEnabled</td>
<td>Allows using ResultHandler on nested statements. If allow, set the false.</td>
<td>true | false</td>
<td>True</td></tr>
<tr class="b">
<td>mapUnderscoreToCamelCase</td>
<td>Enables automatic mapping from classic database column names A_COLUMN to camel case classic Java property names aColumn.</td>
<td>true | false</td>
<td>False</td></tr>
<tr class="a">
<td>localCacheScope</td>
<td>MyBatis uses local cache to prevent circular references and speed up repeated nested queries. By default (SESSION) all queries executed during a session are cached. If localCacheScope=STATEMENT local session will be used just for statement execution, no data will be shared between two different calls to the same SqlSession.</td>
<td>SESSION | STATEMENT</td>
<td>SESSION</td></tr>
<tr class="b">
<td>jdbcTypeForNull</td>
<td>Specifies the JDBC type for null values when no specific JDBC type was provided for the parameter. Some drivers require specifying the column JDBC type but others work with generic values like NULL, VARCHAR or OTHER.</td>
<td>JdbcType enumeration. Most common are: NULL, VARCHAR and OTHER</td>
<td>OTHER</td></tr>
<tr class="a">
<td>lazyLoadTriggerMethods</td>
<td>Specifies which Object's methods trigger a lazy load</td>
<td>A method name list separated by commas</td>
<td>equals,clone,hashCode,toString</td></tr>
<tr class="b">
<td>defaultScriptingLanguage</td>
<td>Specifies the language used by default for dynamic SQL generation.</td>
<td>A type alias or fully qualified class name.</td>
<td>org.apache.ibatis.scripting.xmltags.XMLLanguageDriver</td></tr>
<tr class="a">
<td>defaultEnumTypeHandler</td>
<td>Specifies the <code>TypeHandler</code> used by default for Enum. (Since: 3.4.5)</td>
<td>A type alias or fully qualified class name.</td>
<td>org.apache.ibatis.type.EnumTypeHandler</td></tr>
<tr class="b">
<td>callSettersOnNulls</td>
<td>Specifies if setters or map's put method will be called when a retrieved value is null. It is useful when you rely on Map.keySet() or null value initialization. Note primitives such as (int,boolean,etc.) will not be set to null.</td>
<td>true | false</td>
<td>false</td></tr>
<tr class="a">
<td>returnInstanceForEmptyRow</td>
<td>MyBatis, by default, returns <code>null</code> when all the columns of a returned row are NULL. When this setting is enabled, MyBatis returns an empty instance instead. Note that it is also applied to nested results (i.e. collection and association). Since: 3.4.2</td>
<td>true | false</td>
<td>false</td></tr>
<tr class="b">
<td>logPrefix</td>
<td>Specifies the prefix string that MyBatis will add to the logger names.</td>
<td>Any String</td>
<td>Not set</td></tr>
<tr class="a">
<td>logImpl</td>
<td>Specifies which logging implementation MyBatis should use. If this setting is not present logging implementation will be autodiscovered.</td>
<td>SLF4J | LOG4J(deprecated since 3.5.9) | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING</td>
<td>Not set</td></tr>
<tr class="b">
<td>proxyFactory</td>
<td>Specifies the proxy tool that MyBatis will use for creating lazy loading capable objects.</td>
<td>CGLIB (deprecated since 3.5.10) | JAVASSIST</td>
<td>JAVASSIST (MyBatis 3.3 or above)</td></tr>
<tr class="a">
<td>vfsImpl</td>
<td>Specifies VFS implementations</td>
<td>Fully qualified class names of custom VFS implementation separated by commas.</td>
<td>Not set</td></tr>
<tr class="b">
<td>useActualParamName</td>
<td>Allow referencing statement parameters by their actual names declared in the method signature. To use this feature, your project must be compiled in Java 8 with <code>-parameters</code> option. (Since: 3.4.1)</td>
<td>true | false</td>
<td>true</td></tr>
<tr class="a">
<td>configurationFactory</td>
<td>Specifies the class that provides an instance of <code>Configuration</code>. The returned Configuration instance is used to load lazy properties of deserialized objects. This class must have a method with a signature <code>static Configuration getConfiguration()</code>. (Since: 3.2.3)</td>
<td>A type alias or fully qualified class name.</td>
<td>Not set</td></tr>
<tr class="b">
<td>shrinkWhitespacesInSql</td>
<td>Removes extra whitespace characters from the SQL. Note that this also affects literal strings in SQL. (Since 3.5.5)</td>
<td>true | false</td>
<td>false</td></tr>
<tr class="a">
<td>defaultSqlProviderType</td>
<td>Specifies an sql provider class that holds provider method (Since 3.5.6). This class apply to the <code>type</code>(or <code>value</code>) attribute on sql provider annotation(e.g. <code>@SelectProvider</code>), when these attribute was omitted.</td>
<td>A type alias or fully qualified class name</td>
<td>Not set</td></tr>
<tr class="b">
<td>nullableOnForEach</td>
<td>Specifies the default value of ‘nullable’ attribute on ‘foreach’ tag. (Since 3.5.9)</td>
<td>true | false</td>
<td>false</td></tr>
<tr class="a">
<td>argNameBasedConstructorAutoMapping</td>
<td>When applying constructor auto-mapping, argument name is used to search the column to map instead of relying on the column order. (Since 3.5.10)</td>
<td>true | false</td>
<td>false</td></tr></tbody>
</table>
<p>An example of the settings element fully configured is as follows:</p>
<pre class="prettyprint"><code class="language-xml"><settings>
<setting name="cacheEnabled" value="true"/>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="true"/>
<setting name="useColumnLabel" value="true"/>
<setting name="useGeneratedKeys" value="false"/>
<setting name="autoMappingBehavior" value="PARTIAL"/>
<setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
<setting name="defaultExecutorType" value="SIMPLE"/>
<setting name="defaultStatementTimeout" value="25"/>
<setting name="defaultFetchSize" value="100"/>
<setting name="safeRowBoundsEnabled" value="false"/>
<setting name="safeResultHandlerEnabled" value="true"/>
<setting name="mapUnderscoreToCamelCase" value="false"/>
<setting name="localCacheScope" value="SESSION"/>
<setting name="jdbcTypeForNull" value="OTHER"/>
<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
<setting name="defaultScriptingLanguage" value="org.apache.ibatis.scripting.xmltags.XMLLanguageDriver"/>
<setting name="defaultEnumTypeHandler" value="org.apache.ibatis.type.EnumTypeHandler"/>
<setting name="callSettersOnNulls" value="false"/>
<setting name="returnInstanceForEmptyRow" value="false"/>
<setting name="logPrefix" value="exampleLogPreFix_"/>
<setting name="logImpl" value="SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING"/>
<setting name="proxyFactory" value="CGLIB | JAVASSIST"/>
<setting name="vfsImpl" value="org.mybatis.example.YourselfVfsImpl"/>
<setting name="useActualParamName" value="true"/>
<setting name="configurationFactory" value="org.mybatis.example.ConfigurationFactory"/>
</settings>
</code></pre></section><section><a id="typeAliases"></a>
<h3>typeAliases</h3>
<p>A type alias is simply a shorter name for a Java type. It's only relevant to the XML configuration and simply exists to reduce redundant typing of fully qualified classnames. For example:</p>
<pre class="prettyprint"><code class="language-xml"><typeAliases>
<typeAlias alias="Author" type="domain.blog.Author"/>
<typeAlias alias="Blog" type="domain.blog.Blog"/>
<typeAlias alias="Comment" type="domain.blog.Comment"/>
<typeAlias alias="Post" type="domain.blog.Post"/>
<typeAlias alias="Section" type="domain.blog.Section"/>
<typeAlias alias="Tag" type="domain.blog.Tag"/>
</typeAliases>
</code></pre>
<p>With this configuration, <code>Blog</code> can now be used anywhere that <code>domain.blog.Blog</code> could be.</p>
<p>You can also specify a package where MyBatis will search for beans. For example:</p>
<pre class="prettyprint"><code class="language-xml"><typeAliases>
<package name="domain.blog"/>
</typeAliases>
</code></pre>
<p>Each bean found in <code>domain.blog</code> , if no annotation is found, will be registered as an alias using uncapitalized non-qualified class name of the bean. That is <code>domain.blog.Author</code> will be registered as <code>author</code>. If the <code>@Alias</code> annotation is found its value will be used as an alias. See the example below:</p>
<pre class="prettyprint"><code class="language-java">@Alias("author")
public class Author {
...
}
</code></pre>
<p>There are many built-in type aliases for common Java types. They are all case insensitive, note the special handling of primitives due to the overloaded names.</p>
<table class="table table-striped">
<thead>
<tr class="a">
<th>Alias</th>
<th>Mapped Type</th></tr></thead><tbody>
<tr class="b">
<td>_byte</td>
<td>byte</td></tr>
<tr class="a">
<td>_char (since 3.5.10)</td>
<td>char</td></tr>
<tr class="b">
<td>_character (since 3.5.10)</td>
<td>char</td></tr>
<tr class="a">
<td>_long</td>
<td>long</td></tr>
<tr class="b">
<td>_short</td>
<td>short</td></tr>
<tr class="a">
<td>_int</td>
<td>int</td></tr>
<tr class="b">
<td>_integer</td>
<td>int</td></tr>
<tr class="a">
<td>_double</td>
<td>double</td></tr>
<tr class="b">
<td>_float</td>
<td>float</td></tr>
<tr class="a">
<td>_boolean</td>
<td>boolean</td></tr>
<tr class="b">
<td>string</td>
<td>String</td></tr>
<tr class="a">
<td>byte</td>
<td>Byte</td></tr>
<tr class="b">
<td>char (since 3.5.10)</td>
<td>Character</td></tr>
<tr class="a">
<td>character (since 3.5.10)</td>
<td>Character</td></tr>
<tr class="b">
<td>long</td>
<td>Long</td></tr>
<tr class="a">
<td>short</td>
<td>Short</td></tr>
<tr class="b">
<td>int</td>
<td>Integer</td></tr>
<tr class="a">
<td>integer</td>
<td>Integer</td></tr>
<tr class="b">
<td>double</td>
<td>Double</td></tr>
<tr class="a">
<td>float</td>
<td>Float</td></tr>
<tr class="b">
<td>boolean</td>
<td>Boolean</td></tr>
<tr class="a">
<td>date</td>
<td>Date</td></tr>
<tr class="b">
<td>decimal</td>
<td>BigDecimal</td></tr>
<tr class="a">
<td>bigdecimal</td>
<td>BigDecimal</td></tr>
<tr class="b">
<td>biginteger</td>
<td>BigInteger</td></tr>
<tr class="a">
<td>object</td>
<td>Object</td></tr>
<tr class="b">
<td>date[]</td>
<td>Date[]</td></tr>
<tr class="a">
<td>decimal[]</td>
<td>BigDecimal[]</td></tr>
<tr class="b">
<td>bigdecimal[]</td>
<td>BigDecimal[]</td></tr>
<tr class="a">
<td>biginteger[]</td>
<td>BigInteger[]</td></tr>
<tr class="b">
<td>object[]</td>
<td>Object[]</td></tr>
<tr class="a">
<td>map</td>
<td>Map</td></tr>
<tr class="b">
<td>hashmap</td>
<td>HashMap</td></tr>
<tr class="a">
<td>list</td>
<td>List</td></tr>
<tr class="b">
<td>arraylist</td>
<td>ArrayList</td></tr>
<tr class="a">
<td>collection</td>
<td>Collection</td></tr>
<tr class="b">
<td>iterator</td>
<td>Iterator</td></tr></tbody>
</table>
</section><section><a id="typeHandlers"></a>
<h3>typeHandlers</h3>
<p>Whenever MyBatis sets a parameter on a PreparedStatement or retrieves a value from a ResultSet, a TypeHandler is used to retrieve the value in a means appropriate to the Java type. The following table describes the default TypeHandlers.</p>
<p><span class="label important">NOTE</span> Since version 3.4.5, MyBatis supports JSR-310 (Date and Time API) by default.</p>
<table class="table table-striped">
<thead>
<tr class="a">
<th>Type Handler</th>
<th>Java Types</th>
<th>JDBC Types</th></tr></thead><tbody>
<tr class="b">
<td><code>BooleanTypeHandler</code></td>
<td><code>java.lang.Boolean</code>, <code>boolean</code></td>
<td>Any compatible <code>BOOLEAN</code></td></tr>
<tr class="a">
<td><code>ByteTypeHandler</code></td>
<td><code>java.lang.Byte</code>, <code>byte</code></td>
<td>Any compatible <code>NUMERIC</code> or <code>BYTE</code></td></tr>
<tr class="b">
<td><code>ShortTypeHandler</code></td>
<td><code>java.lang.Short</code>, <code>short</code></td>
<td>Any compatible <code>NUMERIC</code> or <code>SMALLINT</code></td></tr>
<tr class="a">
<td><code>IntegerTypeHandler</code></td>
<td><code>java.lang.Integer</code>, <code>int</code></td>
<td>Any compatible <code>NUMERIC</code> or <code>INTEGER</code></td></tr>
<tr class="b">
<td><code>LongTypeHandler</code></td>
<td><code>java.lang.Long</code>, <code>long</code></td>
<td>Any compatible <code>NUMERIC</code> or <code>BIGINT</code></td></tr>
<tr class="a">
<td><code>FloatTypeHandler</code></td>
<td><code>java.lang.Float</code>, <code>float</code></td>
<td>Any compatible <code>NUMERIC</code> or <code>FLOAT</code></td></tr>
<tr class="b">
<td><code>DoubleTypeHandler</code></td>
<td><code>java.lang.Double</code>, <code>double</code></td>
<td>Any compatible <code>NUMERIC</code> or <code>DOUBLE</code></td></tr>
<tr class="a">
<td><code>BigDecimalTypeHandler</code></td>
<td><code>java.math.BigDecimal</code></td>
<td>Any compatible <code>NUMERIC</code> or <code>DECIMAL</code></td></tr>
<tr class="b">
<td><code>StringTypeHandler</code></td>
<td><code>java.lang.String</code></td>
<td><code>CHAR</code>, <code>VARCHAR</code></td></tr>
<tr class="a">
<td><code>ClobReaderTypeHandler</code></td>
<td><code>java.io.Reader</code></td>
<td>-</td></tr>
<tr class="b">
<td><code>ClobTypeHandler</code></td>
<td><code>java.lang.String</code></td>
<td><code>CLOB</code>, <code>LONGVARCHAR</code></td></tr>
<tr class="a">
<td><code>NStringTypeHandler</code></td>
<td><code>java.lang.String</code></td>
<td><code>NVARCHAR</code>, <code>NCHAR</code></td></tr>
<tr class="b">
<td><code>NClobTypeHandler</code></td>
<td><code>java.lang.String</code></td>
<td><code>NCLOB</code></td></tr>
<tr class="a">
<td><code>BlobInputStreamTypeHandler</code></td>
<td><code>java.io.InputStream</code></td>
<td>-</td></tr>
<tr class="b">
<td><code>ByteArrayTypeHandler</code></td>
<td><code>byte[]</code></td>
<td>Any compatible byte stream type</td></tr>
<tr class="a">
<td><code>BlobTypeHandler</code></td>
<td><code>byte[]</code></td>
<td><code>BLOB</code>, <code>LONGVARBINARY</code></td></tr>
<tr class="b">
<td><code>DateTypeHandler</code></td>
<td><code>java.util.Date</code></td>
<td><code>TIMESTAMP</code></td></tr>
<tr class="a">
<td><code>DateOnlyTypeHandler</code></td>
<td><code>java.util.Date</code></td>
<td><code>DATE</code></td></tr>
<tr class="b">
<td><code>TimeOnlyTypeHandler</code></td>
<td><code>java.util.Date</code></td>
<td><code>TIME</code></td></tr>
<tr class="a">
<td><code>SqlTimestampTypeHandler</code></td>
<td><code>java.sql.Timestamp</code></td>
<td><code>TIMESTAMP</code></td></tr>
<tr class="b">
<td><code>SqlDateTypeHandler</code></td>
<td><code>java.sql.Date</code></td>
<td><code>DATE</code></td></tr>
<tr class="a">
<td><code>SqlTimeTypeHandler</code></td>
<td><code>java.sql.Time</code></td>
<td><code>TIME</code></td></tr>
<tr class="b">
<td><code>ObjectTypeHandler</code></td>
<td>Any</td>
<td><code>OTHER</code>, or unspecified</td></tr>
<tr class="a">
<td><code>EnumTypeHandler</code></td>
<td>Enumeration Type</td>
<td><code>VARCHAR</code> any string compatible type, as the code is stored (not index).</td></tr>
<tr class="b">
<td><code>EnumOrdinalTypeHandler</code></td>
<td>Enumeration Type</td>
<td>Any compatible <code>NUMERIC</code> or <code>DOUBLE</code>, as the position is stored (not the code itself).</td></tr>
<tr class="a">
<td><code>SqlxmlTypeHandler</code></td>
<td><code>java.lang.String</code></td>
<td><code>SQLXML</code></td></tr>
<tr class="b">
<td><code>InstantTypeHandler</code></td>
<td><code>java.time.Instant</code></td>
<td><code>TIMESTAMP</code></td></tr>
<tr class="a">
<td><code>LocalDateTimeTypeHandler</code></td>
<td><code>java.time.LocalDateTime</code></td>
<td><code>TIMESTAMP</code></td></tr>
<tr class="b">
<td><code>LocalDateTypeHandler</code></td>
<td><code>java.time.LocalDate</code></td>
<td><code>DATE</code></td></tr>
<tr class="a">
<td><code>LocalTimeTypeHandler</code></td>
<td><code>java.time.LocalTime</code></td>
<td><code>TIME</code></td></tr>
<tr class="b">
<td><code>OffsetDateTimeTypeHandler</code></td>
<td><code>java.time.OffsetDateTime</code></td>
<td><code>TIMESTAMP</code></td></tr>
<tr class="a">
<td><code>OffsetTimeTypeHandler</code></td>
<td><code>java.time.OffsetTime</code></td>
<td><code>TIME</code></td></tr>
<tr class="b">
<td><code>ZonedDateTimeTypeHandler</code></td>
<td><code>java.time.ZonedDateTime</code></td>
<td><code>TIMESTAMP</code></td></tr>
<tr class="a">
<td><code>YearTypeHandler</code></td>
<td><code>java.time.Year</code></td>
<td><code>INTEGER</code></td></tr>
<tr class="b">
<td><code>MonthTypeHandler</code></td>
<td><code>java.time.Month</code></td>
<td><code>INTEGER</code></td></tr>
<tr class="a">
<td><code>YearMonthTypeHandler</code></td>
<td><code>java.time.YearMonth</code></td>
<td><code>VARCHAR</code> or <code>LONGVARCHAR</code></td></tr>
<tr class="b">
<td><code>JapaneseDateTypeHandler</code></td>
<td><code>java.time.chrono.JapaneseDate</code></td>
<td><code>DATE</code></td></tr></tbody>
</table>
<p>You can override the type handlers or create your own to deal with unsupported or non-standard types. To do so, implement the interface <code>org.apache.ibatis.type.TypeHandler</code> or extend the convenience class <code>org.apache.ibatis.type.BaseTypeHandler</code> and optionally map it to a JDBC type. For example:</p>
<pre class="prettyprint"><code class="language-java">// ExampleTypeHandler.java
@MappedJdbcTypes(JdbcType.VARCHAR)
public class ExampleTypeHandler extends BaseTypeHandler<String> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i,
String parameter, JdbcType jdbcType) throws SQLException {
ps.setString(i, parameter);
}
@Override
public String getNullableResult(ResultSet rs, String columnName)
throws SQLException {
return rs.getString(columnName);
}
@Override
public String getNullableResult(ResultSet rs, int columnIndex)
throws SQLException {
return rs.getString(columnIndex);
}
@Override
public String getNullableResult(CallableStatement cs, int columnIndex)
throws SQLException {
return cs.getString(columnIndex);
}
}
</code></pre>
<pre class="prettyprint"><code class="language-xml"><!-- mybatis-config.xml -->
<typeHandlers>
<typeHandler handler="org.mybatis.example.ExampleTypeHandler"/>
</typeHandlers>
</code></pre>
<p>Using such a TypeHandler would override the existing type handler for Java String properties and VARCHAR parameters and results. Note that MyBatis does not introspect upon the database metadata to determine the type, so you must specify that it’s a VARCHAR field in the parameter and result mappings to hook in the correct type handler. This is due to the fact that MyBatis is unaware of the data type until the statement is executed.</p>
<p>MyBatis will know the Java type that you want to handle with this TypeHandler by introspecting its generic type, but you can override this behavior by two means:</p>
<ul>
<li>Adding a <code>javaType</code> attribute to the typeHandler element (for example: <code>javaType="String"</code>)</li>
<li>Adding a <code>@MappedTypes</code> annotation to your TypeHandler class specifying the list of java types to associate it with. This annotation will be ignored if the <code>javaType</code> attribute as also been specified.</li>
</ul>
<p>The associated JDBC type can be specified by two means:</p>
<ul>
<li>Adding a <code>jdbcType</code> attribute to the typeHandler element (for example: <code>jdbcType="VARCHAR"</code>).</li>
<li>Adding a <code>@MappedJdbcTypes</code> annotation to your TypeHandler class specifying the list of JDBC types to associate it with. This annotation will be ignored if the <code>jdbcType</code> attribute as also been specified.</li>
</ul>
<p>When deciding which TypeHandler to use in a <code>ResultMap</code>, the Java type is known (from the result type), but the JDBC type is unknown. MyBatis therefore uses the combination <code>javaType=[TheJavaType], jdbcType=null</code> to choose a TypeHandler. This means that using a <code>@MappedJdbcTypes</code> annotation <em>restricts</em> the scope of a TypeHandler and makes it unavailable for use in <code>ResultMap</code>s unless explicitly set. To make a TypeHandler available for use in a <code>ResultMap</code>, set <code>includeNullJdbcType=true</code> on the <code>@MappedJdbcTypes</code> annotation. Since Mybatis 3.4.0 however, if a <strong>single</strong> TypeHandler is registered to handle a Java type, it will be used by default in <code>ResultMap</code>s using this Java type (i.e. even without <code>includeNullJdbcType=true</code>).</p>
<p>And finally you can let MyBatis search for your TypeHandlers:</p>
<pre class="prettyprint"><code class="language-xml"><!-- mybatis-config.xml -->
<typeHandlers>
<package name="org.mybatis.example"/>
</typeHandlers>
</code></pre>
<p>Note that when using the autodiscovery feature JDBC types can only be specified with annotations.</p>
<p>You can create a generic TypeHandler that is able to handle more than one class. For that purpose add a constructor that receives the class as a parameter and MyBatis will pass the actual class when constructing the TypeHandler.</p>
<pre class="prettyprint"><code class="language-java">//GenericTypeHandler.java
public class GenericTypeHandler<E extends MyObject> extends BaseTypeHandler<E> {
private Class<E> type;
public GenericTypeHandler(Class<E> type) {
if (type == null) throw new IllegalArgumentException("Type argument cannot be null");
this.type = type;
}
...
</code></pre>
<p><code>EnumTypeHandler</code> and <code>EnumOrdinalTypeHandler</code> are generic TypeHandlers. We will learn about them in the following section.</p></section><section><a id="Handling_Enums"></a>
<h3>Handling Enums</h3>
<p>If you want to map an <code>Enum</code>, you'll need to use either <code>EnumTypeHandler</code> or <code>EnumOrdinalTypeHandler</code>.</p>
<p>For example, let's say that we need to store the rounding mode that should be used with some number if it needs to be rounded. By default, MyBatis uses <code>EnumTypeHandler</code> to convert the <code>Enum</code> values to their names.</p>
<p><strong>Note <code>EnumTypeHandler</code> is special in the sense that unlike other handlers, it does not handle just one specific class, but any class that extends <code>Enum</code></strong></p>
<p>However, we may not want to store names. Our DBA may insist on an integer code instead. That's just as easy: add <code>EnumOrdinalTypeHandler</code> to the <code>typeHandlers</code> in your config file, and now each <code>RoundingMode</code> will be mapped to an integer using its ordinal value.</p>
<pre class="prettyprint"><code class="language-xml"><!-- mybatis-config.xml -->
<typeHandlers>
<typeHandler handler="org.apache.ibatis.type.EnumOrdinalTypeHandler"
javaType="java.math.RoundingMode"/>
</typeHandlers>
</code></pre>
<p>But what if you want to map the same <code>Enum</code> to a string in one place and to integer in another?</p>
<p>The auto-mapper will automatically use <code>EnumOrdinalTypeHandler</code>, so if we want to go back to using plain old ordinary <code>EnumTypeHandler</code>, we have to tell it, by explicitly setting the type handler to use for those SQL statements.</p>
<p>(Mapper files aren't covered until the next section, so if this is your first time reading through the documentation, you may want to skip this for now and come back to it later.)</p>
<pre class="prettyprint"><code class="language-xml"><!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.apache.ibatis.submitted.rounding.Mapper">
<resultMap type="org.apache.ibatis.submitted.rounding.User" id="usermap">
<id column="id" property="id"/>
<result column="name" property="name"/>
<result column="funkyNumber" property="funkyNumber"/>
<result column="roundingMode" property="roundingMode"/>
</resultMap>
<select id="getUser" resultMap="usermap">
select * from users
</select>
<insert id="insert">
insert into users (id, name, funkyNumber, roundingMode) values (
#{id}, #{name}, #{funkyNumber}, #{roundingMode}
)
</insert>
<resultMap type="org.apache.ibatis.submitted.rounding.User" id="usermap2">
<id column="id" property="id"/>
<result column="name" property="name"/>
<result column="funkyNumber" property="funkyNumber"/>
<result column="roundingMode" property="roundingMode"
typeHandler="org.apache.ibatis.type.EnumTypeHandler"/>
</resultMap>
<select id="getUser2" resultMap="usermap2">
select * from users2
</select>
<insert id="insert2">
insert into users2 (id, name, funkyNumber, roundingMode) values (
#{id}, #{name}, #{funkyNumber}, #{roundingMode, typeHandler=org.apache.ibatis.type.EnumTypeHandler}
)
</insert>
</mapper>
</code></pre>
<p>Note that this forces us to use a <code>resultMap</code> instead of a <code>resultType</code> in our select statements.</p></section><section><a id="objectFactory"></a>
<h3>objectFactory</h3>
<p>Each time MyBatis creates a new instance of a result object, it uses an ObjectFactory instance to do so. The default ObjectFactory does little more than instantiate the target class with a default constructor, or a parameterized constructor if parameter mappings exist. If you want to override the default behaviour of the ObjectFactory, you can create your own. For example:</p>
<pre class="prettyprint"><code class="language-java">// ExampleObjectFactory.java
public class ExampleObjectFactory extends DefaultObjectFactory {
@Override
public <T> T create(Class<T> type) {
return super.create(type);
}
@Override
public <T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
return super.create(type, constructorArgTypes, constructorArgs);
}
@Override
public void setProperties(Properties properties) {
super.setProperties(properties);
}
@Override
public <T> boolean isCollection(Class<T> type) {
return Collection.class.isAssignableFrom(type);
}
}
</code></pre>
<pre class="prettyprint"><code class="language-xml"><!-- mybatis-config.xml -->
<objectFactory type="org.mybatis.example.ExampleObjectFactory">
<property name="someProperty" value="100"/>
</objectFactory>
</code></pre>
<p>The ObjectFactory interface is very simple. It contains two create methods, one to deal with the default constructor, and the other to deal with parameterized constructors. Finally, the setProperties method can be used to configure the ObjectFactory. Properties defined within the body of the objectFactory element will be passed to the setProperties method after initialization of your ObjectFactory instance.</p></section><section><a id="plugins"></a>
<h3>plugins</h3>
<p>MyBatis allows you to intercept calls to at certain points within the execution of a mapped statement. By default, MyBatis allows plug-ins to intercept method calls of:</p>
<ul>
<li>Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)</li>
<li>ParameterHandler (getParameterObject, setParameters)</li>
<li>ResultSetHandler (handleResultSets, handleOutputParameters)</li>
<li>StatementHandler (prepare, parameterize, batch, update, query)</li>
</ul>
<p>The details of these classes methods can be discovered by looking at the full method signature of each, and the source code which is available with each MyBatis release. You should understand the behaviour of the method you’re overriding, assuming you’re doing something more than just monitoring calls. If you attempt to modify or override the behaviour of a given method, you’re likely to break the core of MyBatis. These are low level classes and methods, so use plug-ins with caution.</p>
<p>Using plug-ins is pretty simple given the power they provide. Simply implement the Interceptor interface, being sure to specify the signatures you want to intercept.</p>
<pre class="prettyprint"><code class="language-java">// ExamplePlugin.java
@Intercepts({@Signature(
type= Executor.class,
method = "update",
args = {MappedStatement.class,Object.class})})
public class ExamplePlugin implements Interceptor {
private Properties properties = new Properties();
@Override
public Object intercept(Invocation invocation) throws Throwable {
// implement pre-processing if needed
Object returnObject = invocation.proceed();
// implement post-processing if needed
return returnObject;
}
@Override
public void setProperties(Properties properties) {
this.properties = properties;
}
}
</code></pre>
<pre class="prettyprint"><code class="language-xml"><!-- mybatis-config.xml -->
<plugins>
<plugin interceptor="org.mybatis.example.ExamplePlugin">
<property name="someProperty" value="100"/>
</plugin>
</plugins>
</code></pre>
<p>The plug-in above will intercept all calls to the “update” method on the Executor instance, which is an internal object responsible for the low-level execution of mapped statements.</p>
<p><span class="label important">NOTE</span> <strong>Overriding the Configuration Class</strong></p>
<p>In addition to modifying core MyBatis behaviour with plugins, you can also override the <code>Configuration</code> class entirely. Simply extend it and override any methods inside, and pass it into the call to the <code>SqlSessionFactoryBuilder.build(myConfig)</code> method. Again though, this could have a severe impact on the behaviour of MyBatis, so use caution.</p></section><section><a id="environments"></a>
<h3>environments</h3>
<p>MyBatis can be configured with multiple environments. This helps you to apply your SQL Maps to multiple databases for any number of reasons. For example, you might have a different configuration for your Development, Test and Production environments. Or, you may have multiple production databases that share the same schema, and you’d like to use the same SQL maps for both. There are many use cases.</p>
<p><strong>One important thing to remember though: While you can configure multiple environments, you can only choose ONE per SqlSessionFactory instance.</strong></p>
<p>So if you want to connect to two databases, you need to create two instances of SqlSessionFactory, one for each. For three databases, you’d need three instances, and so on. It’s really easy to remember:</p>
<ul>
<li><strong>One SqlSessionFactory instance per database</strong></li>
</ul>
<p>To specify which environment to build, you simply pass it to the SqlSessionFactoryBuilder as an optional parameter. The two signatures that accept the environment are:</p>
<pre class="prettyprint"><code class="language-java">SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment);
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment, properties);
</code></pre>
<p>If the environment is omitted, then the default environment is loaded, as follows:</p>
<pre class="prettyprint"><code class="language-java">SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, properties);
</code></pre>
<p>The environments element defines how the environment is configured.</p>
<pre class="prettyprint"><code class="language-xml"><environments default="development">
<environment id="development">
<transactionManager type="JDBC">
<property name="..." value="..."/>
</transactionManager>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
</code></pre>
<p>Notice the key sections here:</p>
<ul>
<li>The default Environment ID (e.g. default=“development”).</li>
<li>The Environment ID for each environment defined (e.g. id=“development”).</li>
<li>The TransactionManager configuration (e.g. type=“JDBC”)</li>
<li>The DataSource configuration (e.g. type=“POOLED”)</li>
</ul>
<p>The default environment and the environment IDs are self explanatory. Name them whatever you like, just make sure the default matches one of them.</p>
<p><strong>transactionManager</strong></p>
<p>There are two TransactionManager types (i.e. type=“[JDBC|MANAGED]”) that are included with MyBatis:</p>
<ul>
<li>
<p>JDBC – This configuration simply makes use of the JDBC commit and rollback facilities directly. It relies on the connection retrieved from the dataSource to manage the scope of the transaction. By default, it enables auto-commit when closing the connection for compatibility with some drivers. However, for some drivers, enabling auto-commit is not only unnecessary, but also is an expensive operation. So, since version 3.5.10, you can skip this step by setting the “skipSetAutoCommitOnClose” property to true. For example:</p>
<pre class="prettyprint"><code class="language-xml"><transactionManager type="JDBC">
<property name="skipSetAutoCommitOnClose" value="true"/>
</transactionManager>
</code></pre></li>
<li>
<p>MANAGED – This configuration simply does almost nothing. It never commits, or rolls back a connection. Instead, it lets the container manage the full lifecycle of the transaction (e.g. a JEE Application Server context). By default it does close the connection. However, some containers don’t expect this, and thus if you need to stop it from closing the connection, set the “closeConnection” property to false. For example:</p>
<pre class="prettyprint"><code class="language-xml"><transactionManager type="MANAGED">
<property name="closeConnection" value="false"/>
</transactionManager>
</code></pre></li>
</ul>
<p><span class="label important">NOTE</span> If you are planning to use MyBatis with Spring there is no need to configure any TransactionManager because the Spring module will set its own one overriding any previously set configuration.</p>
<p>Neither of these TransactionManager types require any properties. However, they are both Type Aliases, so in other words, instead of using them, you could put your own fully qualified class name or Type Alias that refers to your own implementation of the TransactionFactory interface.</p>
<pre class="prettyprint"><code class="language-java">public interface TransactionFactory {
default void setProperties(Properties props) { // Since 3.5.2, change to default method
// NOP
}
Transaction newTransaction(Connection conn);
Transaction newTransaction(DataSource dataSource, TransactionIsolationLevel level, boolean autoCommit);
}
</code></pre>
<p>Any properties configured in the XML will be passed to the setProperties() method after instantiation. Your implementation would also need to create a Transaction implementation, which is also a very simple interface:</p>
<pre class="prettyprint"><code class="language-java">public interface Transaction {
Connection getConnection() throws SQLException;
void commit() throws SQLException;
void rollback() throws SQLException;
void close() throws SQLException;
Integer getTimeout() throws SQLException;
}
</code></pre>
<p>Using these two interfaces, you can completely customize how MyBatis deals with Transactions.</p>
<p><strong>dataSource</strong></p>
<p>The dataSource element configures the source of JDBC Connection objects using the standard JDBC DataSource interface.</p>
<p>Most MyBatis applications will configure a dataSource as in the example. However, it’s not required. Realize though, that to facilitate Lazy Loading, this dataSource is required.</p>
<p>There are three built-in dataSource types (i.e. type=“[UNPOOLED|POOLED|JNDI]”):</p>
<p><strong>UNPOOLED</strong> – This implementation of DataSource simply opens and closes a connection each time it is requested. While it’s a bit slower, this is a good choice for simple applications that do not require the performance of immediately available connections. Different databases are also different in this performance area, so for some it may be less important to pool and this configuration will be ideal. The UNPOOLED DataSource has the following properties to configure:</p>
<ul>
<li><code>driver</code> – This is the fully qualified Java class of the JDBC driver (NOT of the DataSource class if your driver includes one).</li>
<li><code>url</code> – This is the JDBC URL for your database instance.</li>
<li><code>username</code> – The database username to log in with.</li>
<li><code>password</code> - The database password to log in with.</li>
<li><code>defaultTransactionIsolationLevel</code> – The default transaction isolation level for connections.</li>
<li><code>defaultNetworkTimeout</code> – The default network timeout value in milliseconds to wait for the database operation to complete. See the API documentation of <code>java.sql.Connection#setNetworkTimeout()</code> for details.</li>
</ul>
<p>Optionally, you can pass properties to the database driver as well. To do this, prefix the properties with <code>driver.</code>, for example:</p>
<ul>
<li><code>driver.encoding=UTF8</code></li>
</ul>
<p>This will pass the property <code>encoding</code>, with the value <code>UTF8</code>, to your database driver via the <code>DriverManager.getConnection(url, driverProperties)</code> method.</p>
<p><strong>POOLED</strong> – This implementation of DataSource pools JDBC Connection objects to avoid the initial connection and authentication time required to create a new Connection instance. This is a popular approach for concurrent web applications to achieve the fastest response.</p>
<p>In addition to the (UNPOOLED) properties above, there are many more properties that can be used to configure the POOLED datasource:</p>
<ul>
<li><code>poolMaximumActiveConnections</code> – This is the number of active (i.e. in use) connections that can exist at any given time. Default: 10</li>
<li><code>poolMaximumIdleConnections</code> – The number of idle connections that can exist at any given time.</li>
<li><code>poolMaximumCheckoutTime</code> – This is the amount of time that a Connection can be “checked out” of the pool before it will be forcefully returned. Default: 20000ms (i.e. 20 seconds)</li>
<li><code>poolTimeToWait</code> – This is a low level setting that gives the pool a chance to print a log status and re-attempt the acquisition of a connection in the case that it’s taking unusually long (to avoid failing silently forever if the pool is misconfigured). Default: 20000ms (i.e. 20 seconds)</li>
<li><code>poolMaximumLocalBadConnectionTolerance</code> – This is a low level setting about tolerance of bad connections got for any thread. If a thread got a bad connection, it may still have another chance to re-attempt to get another connection which is valid. But the retrying times should not more than the sum of <code>poolMaximumIdleConnections</code> and <code>poolMaximumLocalBadConnectionTolerance</code>. Default: 3 (Since: 3.4.5)</li>
<li><code>poolPingQuery</code> – The Ping Query is sent to the database to validate that a connection is in good working order and is ready to accept requests. The default is “NO PING QUERY SET”, which will cause most database drivers to fail with a decent error message.</li>
<li><code>poolPingEnabled</code> – This enables or disables the ping query. If enabled, you must also set the poolPingQuery property with a valid SQL statement (preferably a very fast one). Default: false.</li>
<li><code>poolPingConnectionsNotUsedFor</code> – This configures how often the poolPingQuery will be used. This can be set to match the typical timeout for a database connection, to avoid unnecessary pings. Default: 0 (i.e. all connections are pinged every time – but only if poolPingEnabled is true of course).</li>