• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mybatis / scala / 444

29 Mar 2025 10:33PM CUT coverage: 0.0%. Remained the same
444

push

github

web-flow
Update ci.yaml

drop jdk 22 and 23-ea, add jdk 24

0 of 476 branches covered (0.0%)

0 of 996 relevant lines covered (0.0%)

0.0 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/mybatis-scala-core/src/main/scala/org/mybatis/scala/config/ConfigurationSpace.scala
1
/*
2
 *    Copyright 2011-2015 the original author or authors.
3
 *
4
 *    Licensed under the Apache License, Version 2.0 (the "License");
5
 *    you may not use this file except in compliance with the License.
6
 *    You may obtain a copy of the License at
7
 *
8
 *       https://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 *    Unless required by applicable law or agreed to in writing, software
11
 *    distributed under the License is distributed on an "AS IS" BASIS,
12
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 *    See the License for the specific language governing permissions and
14
 *    limitations under the License.
15
 */
16
package org.mybatis.scala.config
17

18
import org.apache.ibatis.session.{Configuration => MBConfig}
19
import org.apache.ibatis.executor.keygen.{Jdbc3KeyGenerator, NoKeyGenerator, SelectKeyGenerator, KeyGenerator => MBKeyGenerator}
20
import org.apache.ibatis.builder.MapperBuilderAssistant
21
import org.mybatis.scala.mapping._
22
import org.mybatis.scala.cache._
23
import java.util.ArrayList
24
import org.apache.ibatis.mapping.{ResultMapping => MBResultMapping, SqlSource, SqlCommandType, Discriminator}
25
import java.util.Properties
26
//eliminate a feature warning, might be a good idea to define and use traits instead of using structural types
27
import scala.language.reflectiveCalls
28

29
/** Configuration Space (mybatis namespace)
30
  * @constructor Creates an empty configuration space.
31
  * @param configuration myBatis Configuration target
32
  * @param spaceName Space name or namespace
33
  */
34
class ConfigurationSpace(configuration : MBConfig, val spaceName : String = "_DEFAULT_") {
×
35

36
  // == Start primary constructor code ===
37

38
  private val builderAssistant = new MapperBuilderAssistant(configuration, spaceName)
×
39

40
  builderAssistant.setCurrentNamespace(spaceName)
×
41

42
  // == End Primary constructor code ===
43

44
  // == Start of public API ===
45

46
  /** Adds a statement to the space */
47
  def += (s : Statement) : this.type = addStatement(s)
×
48

49
  /** Adds a sequence of statements to the space */
50
  def ++=(ss : Seq[Statement]) : this.type = {
51
    for (s <- ss) addStatement(s)
×
52
    this
×
53
  }
54

55
  /** Adds a mapper to the space */
56
  def ++=(mapper : { def bind : Seq[Statement] }) : this.type = ++=(mapper.bind)
×
57

58
  /** Adds cache support to this space.
59
    * @param impl Cache implementation class
60
    * @param eviction cache eviction policy (LRU,FIFO,WEAK,SOFT)
61
    * @param flushInterval any positive integer in milliseconds.
62
    *        The default is not set, thus no flush interval is used and the cache is only flushed by calls to statements.
63
    * @param size max number of objects that can live in the cache. Default is 1024
64
    * @param readWrite A read-only cache will return the same instance of the cached object to all callers.
65
    *        Thus such objects should not be modified.  This offers a significant performance advantage though.
66
    *        A read-write cache will return a copy (via serialization) of the cached object,
67
    *        this is slower, but safer, and thus the default is true.
68
    * @param props implementation specific properties.
69
    */
70
  def cache(
71
    impl : T[_ <: Cache] = DefaultCache,
×
72
    eviction : T[_ <: Cache] = Eviction.LRU,
×
73
    flushInterval : Long = -1,
×
74
    size : Int = -1,
×
75
    readWrite : Boolean = true,
×
76
    blocking : Boolean = false,
×
77
    props : Properties = null) : this.type = {
×
78

79
    builderAssistant.useNewCache(
×
80
      impl.unwrap,
×
81
      eviction.unwrap,
×
82
      if (flushInterval > -1) flushInterval else null,
×
83
      if (size > -1) size else null,
×
84
      readWrite,
×
85
      blocking,
×
86
      props
×
87
    )
88
    this
×
89
  }
90

91
  /** Reference to an external Cache */
92
  def cacheRef(that : ConfigurationSpace) : this.type = {
93
    builderAssistant.useCacheRef(that.spaceName)
×
94
    this
×
95
  }
96

97
  // == End of public API ===
98

99
  private def addResultMap(rm : ResultMap[_]) : Unit = {
100
    if (rm.fqi == null) {
×
101
      rm.fqi = ConfigurationSpace.generateFQI(spaceName, rm)
×
102
      if (rm.parent != null) addResultMap(rm.parent)
×
103
      val resultMappings = new ArrayList[MBResultMapping]
×
104

105
      // Mappings
106
      for (r <- rm.constructor ++ rm.mappings) {
×
107
        if (r.nestedSelect != null) addStatement(r.nestedSelect)
×
108
        if (r.nestedResultMap != null) addResultMap(r.nestedResultMap)
×
109
        resultMappings add
×
110
          builderAssistant.buildResultMapping(
×
111
            r.resultTypeClass,
×
112
            r.property,
×
113
            r.column,
×
114
            r.javaTypeClass,
×
115
            r.jdbcTypeEnum,
×
116
            resolveFQI(r.nestedSelect),
×
117
            resolveFQI(r.nestedResultMap),
×
118
            r.notNullColumn,
×
119
            r.columnPrefix,
×
120
            r.typeHandlerClass,
×
121
            r.flags
×
122
          )
123
      }
124

125
      // Discriminator
126
      import java.util.HashMap
127
      var discriminator : Discriminator = null
×
128
      rm.discr match {
×
129
        case (column, javaType, jdbcType, typeHandler, cases) =>
×
130
          val discriminatorMap = new HashMap[String,String]
×
131
          for (c <- cases) {
×
132
            addResultMap(c.resultMap)
×
133
            discriminatorMap.put(c.value, c.resultMap.fqi.resolveIn(spaceName))
×
134
          }
135
          discriminator = builderAssistant.buildDiscriminator(
×
136
            rm.resultTypeClass,
×
137
            column,
×
138
            if (javaType == null || javaType.isVoid) classOf[String] else javaType.unwrap,
×
139
            if (jdbcType == null || jdbcType == JdbcType.UNDEFINED) null else jdbcType.unwrap,
×
140
            if (typeHandler == null) null else typeHandler.unwrap,
×
141
            discriminatorMap
×
142
          )
143
        case _ =>
×
144
          // Skip
145
      }
146

147
      // Assemble
148
      builderAssistant.addResultMap(
×
149
        rm.fqi.id,
×
150
        rm.resultTypeClass,
×
151
        if (rm.parent != null) rm.parent.fqi.id else null,
×
152
        discriminator,
×
153
        resultMappings,
×
154
        rm.autoMapping.value
×
155
      )
156

157
    }
158
  }
159

160
  private def resolveFQI(r : { def fqi : FQI}) : String = {
161
    if (r == null) null else r.fqi resolveIn spaceName
×
162
  }
163

164
  private def addStatement(statement : Statement) : this.type = {
165
    if (statement.fqi == null) {
×
166
      statement.fqi = ConfigurationSpace.generateFQI(spaceName, statement)
×
167
      statement match {
×
168
        case stmt : Select =>
×
169
          if (stmt.resultMap != null) addResultMap(stmt.resultMap)
×
170
          builderAssistant.addMappedStatement(
×
171
            stmt.fqi.resolveIn(spaceName),
×
172
            buildDynamicSQL(stmt.xsql),
×
173
            stmt.statementType.unwrap,
×
174
            SqlCommandType.SELECT,
×
175
            if (stmt.fetchSize > 0) stmt.fetchSize else null,
×
176
            if (stmt.timeout > -1) stmt.timeout else null,
×
177
            null,
×
178
            stmt.parameterTypeClass,
×
179
            resolveFQI(stmt.resultMap),
×
180
            stmt.resultTypeClass,
×
181
            stmt.resultSetType.unwrap,
×
182
            stmt.flushCache,
×
183
            stmt.useCache,
×
184
            false, // TODO Issue #577
×
185
            new NoKeyGenerator(),
×
186
            null,
×
187
            null,
×
188
            stmt.databaseId,
×
189
            DefaultScriptingDriver
×
190
          )
191
        case stmt : Insert[_] =>
×
192
          builderAssistant.addMappedStatement(
×
193
            stmt.fqi.resolveIn(spaceName),
×
194
            buildDynamicSQL(stmt.xsql),
×
195
            stmt.statementType.unwrap,
×
196
            SqlCommandType.INSERT,
×
197
            null,
×
198
            if (stmt.timeout > -1) stmt.timeout else null,
×
199
            null,
×
200
            stmt.parameterTypeClass,
×
201
            null,
×
202
            classOf[Int],
×
203
            ResultSetType.FORWARD_ONLY.unwrap,
×
204
            stmt.flushCache,
×
205
            false,
×
206
            false, // TODO Issue #577
×
207
            buildKeyGenerator(stmt.keyGenerator, stmt.parameterTypeClass, stmt.fqi.id, stmt.databaseId),
×
208
            if (stmt.keyGenerator == null) null else stmt.keyGenerator.keyProperty,
×
209
            if (stmt.keyGenerator == null) null else stmt.keyGenerator.keyColumn,
×
210
            stmt.databaseId,
×
211
            DefaultScriptingDriver
×
212
          )
213
        case stmt : Update[_] =>
×
214
          builderAssistant.addMappedStatement(
×
215
            stmt.fqi.resolveIn(spaceName),
×
216
            buildDynamicSQL(stmt.xsql),
×
217
            stmt.statementType.unwrap,
×
218
            SqlCommandType.UPDATE,
×
219
            null,
×
220
            if (stmt.timeout > -1) stmt.timeout else null,
×
221
            null,
×
222
            stmt.parameterTypeClass,
×
223
            null,
×
224
            classOf[Int],
×
225
            ResultSetType.FORWARD_ONLY.unwrap,
×
226
            stmt.flushCache,
×
227
            false,
×
228
            false, // TODO Issue #577
×
229
            new NoKeyGenerator(),
×
230
            null,
×
231
            null,
×
232
            stmt.databaseId,
×
233
            DefaultScriptingDriver
×
234
          )
235
        case stmt : Delete[_] =>
×
236
          builderAssistant.addMappedStatement(
×
237
            stmt.fqi.resolveIn(spaceName),
×
238
            buildDynamicSQL(stmt.xsql),
×
239
            stmt.statementType.unwrap,
×
240
            SqlCommandType.DELETE,
×
241
            null,
×
242
            if (stmt.timeout > -1) stmt.timeout else null,
×
243
            null,
×
244
            stmt.parameterTypeClass,
×
245
            null,
×
246
            classOf[Int],
×
247
            ResultSetType.FORWARD_ONLY.unwrap,
×
248
            stmt.flushCache,
×
249
            false,
×
250
            false, // TODO Issue #577
×
251
            new NoKeyGenerator(),
×
252
            null,
×
253
            null,
×
254
            stmt.databaseId,
×
255
            DefaultScriptingDriver
×
256
          )
257
        case stmt : Perform =>
×
258
          builderAssistant.addMappedStatement(
×
259
            stmt.fqi.resolveIn(spaceName),
×
260
            buildDynamicSQL(stmt.xsql),
×
261
            stmt.statementType.unwrap,
×
262
            SqlCommandType.UPDATE,
×
263
            null,
×
264
            if (stmt.timeout > -1) stmt.timeout else null,
×
265
            null,
×
266
            stmt.parameterTypeClass,
×
267
            null,
×
268
            classOf[Int],
×
269
            ResultSetType.FORWARD_ONLY.unwrap,
×
270
            stmt.flushCache,
×
271
            false,
×
272
            false, // TODO Issue #577
×
273
            new NoKeyGenerator(),
×
274
            null,
×
275
            null,
×
276
            stmt.databaseId,
×
277
            DefaultScriptingDriver
×
278
          )
279
        case unsupported =>
280
          throw new ConfigurationException("Unsupported statement type")
×
281
          //error("Unsupported statement type")
282
      }
283
    }
284
    this
×
285
  }
286

287
  private def buildDynamicSQL(xsql : XSQL) : SqlSource
288
    = new DynamicSQLBuilder(configuration, xsql).build
×
289

290
  private def buildKeyGenerator(generator : KeyGenerator, parameterTypeClass : Class[_], baseId : String, databaseId : String) : MBKeyGenerator = {
291
    generator match {
×
292
      case jdbc : JdbcGeneratedKey =>
×
293
        new Jdbc3KeyGenerator()
×
294
      case sql : SqlGeneratedKey[_] =>
×
295
        buildSqlKeyGenerator(sql, parameterTypeClass, baseId, databaseId)
×
296
      case _ =>
297
        new NoKeyGenerator()
×
298
    }
299
  }
300

301
  private def buildSqlKeyGenerator(generator : SqlGeneratedKey[_], parameterTypeClass : Class[_], baseId : String, databaseId : String) : MBKeyGenerator = {
302

303
    val id = baseId + SelectKeyGenerator.SELECT_KEY_SUFFIX
×
304
    val useCache = false
×
305
    val keyGenerator = new NoKeyGenerator()
×
306
    val fetchSize = null
×
307
    val timeout = null
×
308
    val flushCache = false
×
309
    val parameterMap = null
×
310
    val resultMap = null
×
311
    val resultSetTypeEnum = null
×
312
    val sqlSource = buildDynamicSQL(generator.xsql)
×
313
    val sqlCommandType = SqlCommandType.SELECT
×
314
    val statementType = generator.statementType.unwrap
×
315
    val keyProperty = generator.keyProperty
×
316
    val keyColumn = generator.keyColumn
×
317
    val executeBefore = generator.executeBefore
×
318
    val resultTypeClass = generator.resultTypeClass
×
319

320
    builderAssistant.addMappedStatement(
×
321
      id,
×
322
      sqlSource,
×
323
      statementType,
×
324
      sqlCommandType,
×
325
      fetchSize,
×
326
      timeout,
×
327
      parameterMap,
×
328
      parameterTypeClass,
×
329
      resultMap,
×
330
      resultTypeClass,
×
331
      resultSetTypeEnum,
×
332
      flushCache,
×
333
      useCache,
×
334
      false, // TODO Issue #577
×
335
      keyGenerator,
×
336
      keyProperty,
×
337
      keyColumn,
×
338
      databaseId,
×
339
      DefaultScriptingDriver)
×
340

341
    val keyStatement = configuration.getMappedStatement(id, false)
×
342
    val answer = new SelectKeyGenerator(keyStatement, executeBefore)
×
343

344
    configuration.addKeyGenerator(id, answer)
×
345
    answer
×
346
  }
347

348
}
349

350
private object ConfigurationSpace {
×
351

352
  private var count : Int = 0
×
353

354
  private[config] def generateFQI(spaceId : String, subject : AnyRef) = {
355
    count += 1
×
356
    FQI(spaceId, subject.getClass.getName.replace('.', '-') + "-" + count)
×
357
  }
358

359
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc