1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.mybatis.guice;
17
18 import static com.google.inject.name.Names.named;
19 import static com.google.inject.util.Providers.guicify;
20 import static org.mybatis.guice.Preconditions.checkArgument;
21
22 import com.google.inject.Key;
23 import com.google.inject.Scopes;
24 import com.google.inject.TypeLiteral;
25
26 import jakarta.inject.Provider;
27
28 import java.util.Collection;
29
30 import javax.sql.DataSource;
31
32 import org.apache.ibatis.io.ResolverUtil;
33 import org.apache.ibatis.mapping.DatabaseIdProvider;
34 import org.apache.ibatis.mapping.Environment;
35 import org.apache.ibatis.plugin.Interceptor;
36 import org.apache.ibatis.reflection.factory.DefaultObjectFactory;
37 import org.apache.ibatis.reflection.factory.ObjectFactory;
38 import org.apache.ibatis.reflection.wrapper.DefaultObjectWrapperFactory;
39 import org.apache.ibatis.reflection.wrapper.ObjectWrapperFactory;
40 import org.apache.ibatis.scripting.LanguageDriver;
41 import org.apache.ibatis.scripting.xmltags.XMLLanguageDriver;
42 import org.apache.ibatis.session.AutoMappingBehavior;
43 import org.apache.ibatis.session.Configuration;
44 import org.apache.ibatis.session.ExecutorType;
45 import org.apache.ibatis.session.LocalCacheScope;
46 import org.apache.ibatis.session.SqlSessionFactory;
47 import org.apache.ibatis.transaction.TransactionFactory;
48 import org.apache.ibatis.type.Alias;
49 import org.apache.ibatis.type.TypeHandler;
50 import org.mybatis.guice.binder.AliasBinder;
51 import org.mybatis.guice.binder.TypeHandlerBinder;
52 import org.mybatis.guice.configuration.ConfigurationProvider;
53 import org.mybatis.guice.configuration.ConfigurationSettingListener;
54 import org.mybatis.guice.configuration.settings.AggressiveLazyLoadingConfigurationSetting;
55 import org.mybatis.guice.configuration.settings.AliasConfigurationSetting;
56 import org.mybatis.guice.configuration.settings.AutoMappingBehaviorConfigurationSetting;
57 import org.mybatis.guice.configuration.settings.CacheEnabledConfigurationSetting;
58 import org.mybatis.guice.configuration.settings.ConfigurationSetting;
59 import org.mybatis.guice.configuration.settings.DefaultExecutorTypeConfigurationSetting;
60 import org.mybatis.guice.configuration.settings.DefaultScriptingLanguageTypeConfigurationSetting;
61 import org.mybatis.guice.configuration.settings.DefaultStatementTimeoutConfigurationSetting;
62 import org.mybatis.guice.configuration.settings.InterceptorConfigurationSettingProvider;
63 import org.mybatis.guice.configuration.settings.JavaTypeAndHandlerConfigurationSettingProvider;
64 import org.mybatis.guice.configuration.settings.LazyLoadingEnabledConfigurationSetting;
65 import org.mybatis.guice.configuration.settings.LocalCacheScopeConfigurationSetting;
66 import org.mybatis.guice.configuration.settings.MapUnderscoreToCamelCaseConfigurationSetting;
67 import org.mybatis.guice.configuration.settings.MapperConfigurationSetting;
68 import org.mybatis.guice.configuration.settings.MultipleResultSetsEnabledConfigurationSetting;
69 import org.mybatis.guice.configuration.settings.ObjectFactoryConfigurationSetting;
70 import org.mybatis.guice.configuration.settings.ObjectWrapperFactoryConfigurationSetting;
71 import org.mybatis.guice.configuration.settings.TypeHandlerConfigurationSettingProvider;
72 import org.mybatis.guice.configuration.settings.UseColumnLabelConfigurationSetting;
73 import org.mybatis.guice.configuration.settings.UseGeneratedKeysConfigurationSetting;
74 import org.mybatis.guice.environment.EnvironmentProvider;
75 import org.mybatis.guice.provision.ConfigurationProviderProvisionListener;
76 import org.mybatis.guice.provision.KeyMatcher;
77 import org.mybatis.guice.session.SqlSessionFactoryProvider;
78 import org.mybatis.guice.type.TypeHandlerProvider;
79
80
81
82
83
84 public abstract class MyBatisModule extends AbstractMyBatisModule {
85
86
87
88
89 private Class<? extends ObjectFactory> objectFactoryType = DefaultObjectFactory.class;
90
91
92
93
94 private Class<? extends ObjectWrapperFactory> objectWrapperFactoryType = DefaultObjectWrapperFactory.class;
95 private Class<? extends LanguageDriver> defaultScriptingLanguageType = XMLLanguageDriver.class;
96
97
98
99
100 private Class<? extends Provider<? extends SqlSessionFactory>> sqlSessionFactoryProviderType = SqlSessionFactoryProvider.class;
101
102 private Class<? extends Provider<? extends Configuration>> configurationProviderType = ConfigurationProvider.class;
103
104 @Override
105 final void internalConfigure() {
106 try {
107 initialize();
108
109 } finally {
110
111 }
112
113
114 bind(Environment.class).toProvider(EnvironmentProvider.class).in(Scopes.SINGLETON);
115
116
117 bind(Configuration.class).toProvider(configurationProviderType).in(Scopes.SINGLETON);
118 bind(SqlSessionFactory.class).toProvider(sqlSessionFactoryProviderType);
119
120
121 bind(ObjectFactory.class).to(objectFactoryType).in(Scopes.SINGLETON);
122 bind(ObjectWrapperFactory.class).to(objectWrapperFactoryType).in(Scopes.SINGLETON);
123
124 bindConfigurationSettingProvider(new ObjectFactoryConfigurationSetting(objectFactoryType));
125 bindConfigurationSettingProvider(new ObjectWrapperFactoryConfigurationSetting(objectWrapperFactoryType));
126 bindConfigurationSetting(new DefaultScriptingLanguageTypeConfigurationSetting(defaultScriptingLanguageType));
127 }
128
129
130
131
132
133
134
135 protected final void environmentId(String environmentId) {
136 checkArgument(environmentId != null, "Parameter 'environmentId' must be not null");
137 bindConstant().annotatedWith(named("mybatis.environment.id")).to(environmentId);
138 }
139
140
141
142
143
144
145
146 protected final void lazyLoadingEnabled(boolean lazyLoadingEnabled) {
147 bindConfigurationSetting(new LazyLoadingEnabledConfigurationSetting(lazyLoadingEnabled));
148 }
149
150
151
152
153
154
155
156 protected final void aggressiveLazyLoading(boolean aggressiveLazyLoading) {
157 bindConfigurationSetting(new AggressiveLazyLoadingConfigurationSetting(aggressiveLazyLoading));
158 }
159
160
161
162
163
164
165
166 protected final void multipleResultSetsEnabled(boolean multipleResultSetsEnabled) {
167 bindConfigurationSetting(new MultipleResultSetsEnabledConfigurationSetting(multipleResultSetsEnabled));
168 }
169
170
171
172
173
174
175
176 protected final void useGeneratedKeys(boolean useGeneratedKeys) {
177 bindConfigurationSetting(new UseGeneratedKeysConfigurationSetting(useGeneratedKeys));
178 }
179
180
181
182
183
184
185
186 protected final void useColumnLabel(boolean useColumnLabel) {
187 bindConfigurationSetting(new UseColumnLabelConfigurationSetting(useColumnLabel));
188 }
189
190
191
192
193
194
195
196 protected final void useCacheEnabled(boolean useCacheEnabled) {
197 bindConfigurationSetting(new CacheEnabledConfigurationSetting(useCacheEnabled));
198 }
199
200
201
202
203
204
205
206 protected final void useConfigurationProvider(
207 Class<? extends Provider<? extends Configuration>> configurationProviderType) {
208 this.configurationProviderType = configurationProviderType;
209 }
210
211
212
213
214
215
216
217 protected final void useSqlSessionFactoryProvider(
218 Class<? extends Provider<? extends SqlSessionFactory>> sqlSessionFactoryProvider) {
219 this.sqlSessionFactoryProviderType = sqlSessionFactoryProvider;
220 }
221
222
223
224
225
226
227
228 protected final void failFast(boolean failFast) {
229 bindBoolean("mybatis.configuration.failFast", failFast);
230 }
231
232
233
234
235
236
237
238 protected final void mapUnderscoreToCamelCase(boolean mapUnderscoreToCamelCase) {
239 bindConfigurationSetting(new MapUnderscoreToCamelCaseConfigurationSetting(mapUnderscoreToCamelCase));
240 }
241
242
243
244
245
246
247
248 protected final void defaultStatementTimeout(Integer defaultStatementTimeout) {
249 bindConfigurationSetting(new DefaultStatementTimeoutConfigurationSetting(defaultStatementTimeout));
250 }
251
252 protected final void bindConfigurationSetting(final ConfigurationSetting configurationSetting) {
253 bindListener(KeyMatcher.create(Key.get(ConfigurationSettingListener.class)),
254 ConfigurationProviderProvisionListener.create(configurationSetting));
255 }
256
257 protected final <P extends Provider<? extends ConfigurationSetting>> void bindConfigurationSettingProvider(
258 P configurationSettingProvider) {
259 bindListener(KeyMatcher.create(Key.get(ConfigurationSettingListener.class)),
260 ConfigurationProviderProvisionListener.create(configurationSettingProvider, binder()));
261 }
262
263 private final void bindBoolean(String name, boolean value) {
264 bindConstant().annotatedWith(named(name)).to(value);
265 }
266
267
268
269
270
271
272
273 protected final void executorType(ExecutorType executorType) {
274 checkArgument(executorType != null, "Parameter 'executorType' must be not null");
275 bindConfigurationSetting(new DefaultExecutorTypeConfigurationSetting(executorType));
276 }
277
278
279
280
281
282
283
284
285
286 protected final void localCacheScope(LocalCacheScope localeCacheScope) {
287 checkArgument(localeCacheScope != null, "Parameter 'localCacheScope' must be not null");
288 bindConfigurationSetting(new LocalCacheScopeConfigurationSetting(localeCacheScope));
289 }
290
291
292
293
294
295
296
297 protected final void autoMappingBehavior(AutoMappingBehavior autoMappingBehavior) {
298 checkArgument(autoMappingBehavior != null, "Parameter 'autoMappingBehavior' must be not null");
299 bindConfigurationSetting(new AutoMappingBehaviorConfigurationSetting(autoMappingBehavior));
300 }
301
302
303
304
305
306
307
308 protected final void bindDataSourceProviderType(Class<? extends Provider<DataSource>> dataSourceProviderType) {
309 checkArgument(dataSourceProviderType != null, "Parameter 'dataSourceProviderType' must be not null");
310 bind(DataSource.class).toProvider(dataSourceProviderType).in(Scopes.SINGLETON);
311 }
312
313
314
315
316
317
318
319 protected final void bindDataSourceProvider(Provider<DataSource> dataSourceProvider) {
320 checkArgument(dataSourceProvider != null, "Parameter 'dataSourceProvider' must be not null");
321 bindDataSourceProvider(guicify(dataSourceProvider));
322 }
323
324
325
326
327
328
329
330 protected final void bindDataSourceProvider(com.google.inject.Provider<DataSource> dataSourceProvider) {
331 checkArgument(dataSourceProvider != null, "Parameter 'dataSourceProvider' must be not null");
332 bind(DataSource.class).toProvider(dataSourceProvider).in(Scopes.SINGLETON);
333 }
334
335
336
337
338
339
340
341 protected final void bindDatabaseIdProvider(Class<? extends DatabaseIdProvider> databaseIdProvider) {
342 checkArgument(databaseIdProvider != null, "Parameter 'dataSourceProvider' must be not null");
343 bind(DatabaseIdProvider.class).to(databaseIdProvider).in(Scopes.SINGLETON);
344 }
345
346
347
348
349
350
351
352 protected final void bindDatabaseIdProvider(DatabaseIdProvider databaseIdProvider) {
353 checkArgument(databaseIdProvider != null, "Parameter 'dataSourceProvider' must be not null");
354 bind(DatabaseIdProvider.class).toInstance(databaseIdProvider);
355 }
356
357
358
359
360
361
362
363 protected final void bindTransactionFactoryType(Class<? extends TransactionFactory> transactionFactoryType) {
364 checkArgument(transactionFactoryType != null, "Parameter 'transactionFactoryType' must be not null");
365 bind(TransactionFactory.class).to(transactionFactoryType).in(Scopes.SINGLETON);
366 }
367
368
369
370
371
372
373
374 protected final void bindTransactionFactory(Provider<TransactionFactory> transactionFactoryProvider) {
375 checkArgument(transactionFactoryProvider != null, "Parameter 'transactionFactoryProvider' must be not null");
376 bindTransactionFactory(guicify(transactionFactoryProvider));
377 }
378
379
380
381
382
383
384
385 protected final void bindTransactionFactory(
386 com.google.inject.Provider<TransactionFactory> transactionFactoryProvider) {
387 checkArgument(transactionFactoryProvider != null, "Parameter 'transactionFactoryProvider' must be not null");
388 bind(TransactionFactory.class).toProvider(transactionFactoryProvider).in(Scopes.SINGLETON);
389 }
390
391
392
393
394
395
396
397 protected final void bindObjectFactoryType(Class<? extends ObjectFactory> objectFactoryType) {
398 checkArgument(objectFactoryType != null, "Parameter 'objectFactoryType' must be not null");
399 this.objectFactoryType = objectFactoryType;
400 }
401
402
403
404
405
406
407
408 protected final void bindObjectWrapperFactoryType(Class<? extends ObjectWrapperFactory> objectWrapperFactoryType) {
409 checkArgument(objectFactoryType != null, "Parameter 'objectWrapperFactoryType' must be not null");
410 this.objectWrapperFactoryType = objectWrapperFactoryType;
411 }
412
413
414
415
416
417
418
419
420
421
422 protected final void bindDefaultScriptingLanguageType(Class<? extends LanguageDriver> defaultScriptingLanguageType) {
423 checkArgument(defaultScriptingLanguageType != null, "Parameter 'defaultScriptingLanguageType' must be not null");
424 this.defaultScriptingLanguageType = defaultScriptingLanguageType;
425 }
426
427
428
429
430
431
432
433
434
435 protected final AliasBinder addAlias(final String alias) {
436 checkArgument(alias != null && alias.length() > 0, "Empty or null 'alias' is not valid");
437
438 return new AliasBinder() {
439
440 @Override
441 public void to(final Class<?> clazz) {
442 checkArgument(clazz != null, "Null type not valid for alias '%s'", alias);
443 bindConfigurationSetting(new AliasConfigurationSetting(alias, clazz));
444 }
445
446 };
447 }
448
449
450
451
452
453
454
455
456 protected final void addSimpleAlias(final Class<?> type) {
457 checkArgument(type != null, "Parameter 'type' must be not null");
458
459 String alias = type.getSimpleName();
460
461 final Alias annotation = type.getAnnotation(Alias.class);
462 if (annotation != null) {
463 alias = annotation.value();
464 }
465 addAlias(alias).to(type);
466 }
467
468
469
470
471
472
473
474
475 protected final void addSimpleAliases(final Collection<Class<?>> types) {
476 checkArgument(types != null, "Parameter 'types' must be not null");
477
478 for (Class<?> type : types) {
479 addSimpleAlias(type);
480 }
481 }
482
483
484
485
486
487
488
489
490
491
492 protected final void addSimpleAliases(final String packageName, final ResolverUtil.Test test) {
493 addSimpleAliases(getClasses(test, packageName));
494 }
495
496
497
498
499
500
501
502
503 protected final void addSimpleAliases(final String packageName) {
504 addSimpleAliases(getClasses(packageName));
505 }
506
507
508
509
510
511
512
513
514
515
516
517 protected final <T> TypeHandlerBinder<T> handleType(final Class<T> type) {
518 checkArgument(type != null, "Parameter 'type' must be not null");
519
520 return new TypeHandlerBinder<T>() {
521
522 @Override
523 public void with(final Class<? extends TypeHandler<? extends T>> handler) {
524 checkArgument(handler != null, "TypeHandler must not be null for '%s'", type.getName());
525
526 bindTypeHandler(TypeLiteral.get(handler));
527 bindConfigurationSettingProvider(JavaTypeAndHandlerConfigurationSettingProvider.create(type, Key.get(handler)));
528 }
529
530 @Override
531 public void with(final TypeLiteral<? extends TypeHandler<? extends T>> handler) {
532 checkArgument(handler != null, "TypeHandler must not be null for '%s'", type.getName());
533
534 bindTypeHandler(handler);
535 bindConfigurationSettingProvider(JavaTypeAndHandlerConfigurationSettingProvider.create(type, Key.get(handler)));
536 }
537
538 @Override
539 public void withProvidedTypeHandler(final Class<? extends TypeHandler<? extends T>> handler) {
540 checkArgument(handler != null, "TypeHandler must not be null for '%s'", type.getName());
541
542 bindProvidedTypeHandler(TypeLiteral.get(handler), type);
543 bindConfigurationSettingProvider(JavaTypeAndHandlerConfigurationSettingProvider.create(type, Key.get(handler)));
544 }
545
546 @Override
547 public void withProvidedTypeHandler(final TypeLiteral<? extends TypeHandler<? extends T>> handler) {
548 checkArgument(handler != null, "TypeHandler must not be null for '%s'", type.getName());
549
550 bindProvidedTypeHandler(handler, type);
551 bindConfigurationSettingProvider(JavaTypeAndHandlerConfigurationSettingProvider.create(type, Key.get(handler)));
552 }
553
554 final <TH extends TypeHandler<? extends T>> void bindTypeHandler(TypeLiteral<TH> typeHandlerType) {
555 bind(typeHandlerType).in(Scopes.SINGLETON);
556 }
557
558 final <TH extends TypeHandler<? extends T>> void bindProvidedTypeHandler(TypeLiteral<TH> typeHandlerType,
559 Class<T> type) {
560 bind(typeHandlerType).toProvider(guicify(new TypeHandlerProvider<TH, T>(typeHandlerType, type)))
561 .in(Scopes.SINGLETON);
562 }
563 };
564 }
565
566
567
568
569
570
571
572 protected final void addTypeHandlerClass(final Class<? extends TypeHandler<?>> handlerClass) {
573 checkArgument(handlerClass != null, "Parameter 'handlerClass' must not be null");
574 bind(TypeLiteral.get(handlerClass)).in(Scopes.SINGLETON);
575
576 bindConfigurationSettingProvider(new TypeHandlerConfigurationSettingProvider(Key.get(handlerClass)));
577 }
578
579
580
581
582
583
584
585 protected final void addTypeHandlersClasses(Collection<Class<? extends TypeHandler<?>>> handlersClasses) {
586 checkArgument(handlersClasses != null, "Parameter 'handlersClasses' must not be null");
587
588 for (Class<? extends TypeHandler<?>> handlerClass : handlersClasses) {
589 addTypeHandlerClass(handlerClass);
590 }
591 }
592
593
594
595
596
597
598
599 protected final void addTypeHandlerClasses(String packageName) {
600 checkArgument(packageName != null, "Parameter 'packageName' must not be null");
601 addTypeHandlersClasses(
602 new ResolverUtil<TypeHandler<?>>().find(new ResolverUtil.IsA(TypeHandler.class), packageName).getClasses());
603 }
604
605
606
607
608
609
610
611 protected final void addInterceptorClass(final Class<? extends Interceptor> interceptorClass) {
612 checkArgument(interceptorClass != null, "Parameter 'interceptorClass' must not be null");
613 bindConfigurationSettingProvider(new InterceptorConfigurationSettingProvider(interceptorClass));
614 }
615
616
617
618
619
620
621
622 protected final void addInterceptorsClasses(Collection<Class<? extends Interceptor>> interceptorsClasses) {
623 checkArgument(interceptorsClasses != null, "Parameter 'interceptorsClasses' must not be null");
624
625 for (Class<? extends Interceptor> interceptorClass : interceptorsClasses) {
626 addInterceptorClass(interceptorClass);
627 }
628 }
629
630
631
632
633
634
635
636 protected final void addInterceptorsClasses(String packageName) {
637 checkArgument(packageName != null, "Parameter 'packageName' must not be null");
638 addInterceptorsClasses(
639 new ResolverUtil<Interceptor>().find(new ResolverUtil.IsA(Interceptor.class), packageName).getClasses());
640 }
641
642
643
644
645
646
647
648 protected final void addMapperClass(Class<?> mapperClass) {
649 checkArgument(mapperClass != null, "Parameter 'mapperClass' must not be null");
650
651 bindListener(KeyMatcher.create(Key.get(ConfigurationSettingListener.class)),
652 ConfigurationProviderProvisionListener.create(new MapperConfigurationSetting(mapperClass)));
653 bindMapper(mapperClass);
654 }
655
656
657
658
659
660
661
662 protected final void addMapperClasses(Collection<Class<?>> mapperClasses) {
663 checkArgument(mapperClasses != null, "Parameter 'mapperClasses' must not be null");
664
665 for (Class<?> mapperClass : mapperClasses) {
666 addMapperClass(mapperClass);
667 }
668 }
669
670
671
672
673
674
675
676 protected final void addMapperClasses(final String packageName) {
677 addMapperClasses(getClasses(packageName));
678 }
679
680
681
682
683
684
685
686
687
688 protected final void addMapperClasses(final String packageName, final ResolverUtil.Test test) {
689 addMapperClasses(getClasses(test, packageName));
690 }
691 }