I thought that "Customizer for Platform Transaction Manager will be added from Spring Boot 1.5" posted yesterday was written this year ... : sweat_smile: I've found what I want to write, so I'm really posting the last post of the year: wink:
As a story ... Kotlin 1.1 and MyBatis 3.4.1+ scheduled to be released in 2017 1Q (January to March) (when compiled using the -parameters
option added from Java SE 8, the argument name of the Mapper method is bound. If you combine it with the version that becomes the variable name), you don't need to use @ Param
.
Note:
2017/03/02 Kotlin 1.1 has been officially released, so we've made a complete fix to the release base! !! (The content is basically the same)
For Kotlin 1.0.x ...
@Select("""
SELECT
id, title, details, finished
FROM
todo
WHERE
id = #{id}
AND
finished = #{finished}
""")
fun select(@Param("id") id: Int, @Param("finished") finished: Boolean = false): Todo
I had to specify @ Param
. If you don't specify @ Param
, the bind variable name will be assigned mechanically using the order of the arguments, like pram1
or param2
. (I don't like the order ...)
If you specify -java-parameters
(equivalent to the -parameters
option added from Java SE 8) as a compile option in Kotlin 1.1 ...
@Select("""
SELECT
id, title, details, finished
FROM
todo
WHERE
id = #{id}
AND
finished = #{finished}
""")
fun select(id: Int, finished: Boolean = false): Todo // @Param can be omitted! !!
With that feeling, you can omit the specification of @ Param
: laughing:
Note:
It is supported at https://youtrack.jetbrains.com/issue/KT-8816 and released in Kotlin 1.1-M3.
Seeing is believing ... So let's actually check it using Kotlin 1.1 and MyBatis 3.4.1+. In this post, I will explain based on the previously posted "Use mybatis-spring-boot-starter with Kotlin".
First, fix TodoMapper
as follows. The point is to have multiple arguments for the Mapper method (because there are no particular restrictions on the bind variable name if there is only one argument, it will work no matter what you specify).
src/main/kotlin/com/example/mapper/TodoMapper.kt
@Mapper
interface TodoMapper {
@Insert("""
INSERT INTO todo
(title, details, finished)
VALUES
(#{title}, #{details}, #{finished})
""")
@Options(useGeneratedKeys = true)
fun insert(todo: Todo)
@Select("""
SELECT
id, title, details, finished
FROM
todo
WHERE
id = #{id}
+ AND
+ finished = #{finished}
""")
- fun select(id: Int): Todo
+ fun select(id: Int, finished: Boolean = false): Todo
}
Next, let's fix the caller of the Mapper method.
src/main/kotlin/com/example/MybatisKotlinDemoApplication.kt
@SpringBootApplication
open class MybatisKotlinDemoApplication : CommandLineRunner {
@Autowired
lateinit var todoMapper: TodoMapper
@Transactional
override fun run(vararg args: String?) {
val newTodo: Todo = Todo()
newTodo.title = "drinking party"
newTodo.details = "Ginza 19:00"
todoMapper.insert(newTodo) //Insert a new Todo
- val loadedTodo: Todo = todoMapper.select(newTodo.id)
+ val loadedTodo: Todo = todoMapper.select(id = newTodo.id) //Only id is specified, the default value false is used for finished
println("ID : " + loadedTodo.id)
println("TITLE : " + loadedTodo.title)
println("DETAILS : " + loadedTodo.details)
println("FINISHED : " + loadedTodo.finished)
}
}
fun main(args: Array<String>) {
SpringApplication.run(MybatisKotlinDemoApplication::class.java, *args)
}
Try it ... Let's try using the Maven command to see what happens when it is executed in this state.
$ ./mvnw clean spring-boot:run
The following stack Torres is displayed, and I get an error saying that the bind variable named ʻid` cannot be found.
...
... 12 more
Caused by: org.apache.ibatis.binding.BindingException: Parameter 'id' not found. Available parameters are [0, 1, param1, param2]
at org.apache.ibatis.binding.MapperMethod$ParamMap.get(MapperMethod.java:186)
...
First, let's fix the POM file as follows.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>mybatis-kotlin-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>mybatis-kotlin-demo</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
- <version>1.4.1.RELEASE</version>
+ <version>1.5.1.RELEASE</version> <!--Modified to use the latest at the time of posting update (correction is optional)-->
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
- <kotlin.version>1.0.3</kotlin.version>
+ <kotlin.version>1.1.0</kotlin.version> <!-- 1.Fixed to use the latest of 1-->
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>${kotlin.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
- <version>1.1.1</version>
+ <version>1.2.0</version> <!-- 1.2.By setting it to 0, MyBatis 3.4.2 is transitively added to dependent artifacts-->
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
</dependencies>
<build>
<sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>
<testSourceDirectory>${project.basedir}/src/test/kotlin</testSourceDirectory>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<artifactId>kotlin-maven-plugin</artifactId>
<groupId>org.jetbrains.kotlin</groupId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>test-compile</id>
<phase>test-compile</phase>
<goals>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
+ <configuration>
+ <args>
+ <arg>-java-parameters</arg> <!-- Kotlin 1.Supported by 1-java-Specify parameters option-->
+ </args>
+ </configuration>
</plugin>
</plugins>
</build>
</project>
If you execute the Maven command again after modifying the POM file ...
$ ./mvnw clean spring-boot:run
Now works fine: laughing:
...
2017-03-02 22:00:55.855 INFO 85743 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup
ID : 1
TITLE :drinking party
DETAILS :Ginza 19:00
FINISHED : false
2017-03-02 22:00:55.932 INFO 85743 --- [ main] c.e.MybatisKotlinDemoApplicationKt : Started MybatisKotlinDemoApplicationKt in 1.84 seconds (JVM running for 9.21)
...
Note:
By the way ... If you compile without specifying the
-java-parameters
option ... the argument name will be something like ʻarg0or ʻarg1
, and that value will be used as the bind variable name. The following error will occur.
... ... 12 more Caused by: org.apache.ibatis.binding.BindingException: Parameter 'id' not found. Available parameters are [arg1, arg0, param1, param2] at org.apache.ibatis.binding.MapperMethod$ParamMap.get(MapperMethod.java:195) ...
I was able to confirm that it works using the Maven command, but ... During development, it is common to execute it using the functions of the IDE. In this post, we will configure Kotlin 1.1 to be used on IntelliJ IDEA provided by JetBrains, the developer of Kotlin, and execute the modified program. (It seems that Eclipse Plugin is also available, but I will not handle it this time)
First ... Update to Kotlin 1.1 support Plugin. Select "Tools-> Kotlin-> Configure Kotlin Plugin Updates" from the window menu, select "Stable", click the "Check for updates now" button, and if there is an update target, click the "Install" button to install the plugin. Please update.
Next, set the Kotlin language version and compile options used in the project. After selecting "Preferences-> Build, Execution, Deployment-> Compiler-> Kotlin Compiler from the window menu"
1.1
" -java-parameters
"to" Additional Command Line Parameters "Then click the "OK" button.
After changing the settings, be sure to select ** "Build-> Rebuild Project" from the window menu and rebuild (compile) with the changed settings. (If you forget this, it may not work as expected ...)
Finally ... If you select MybatisKotlinDemoApplication
on the IDE and run the program, it will work fine: laughing:
...
2017-03-02 22:37:28.315 INFO 86040 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup
ID : 1
TITLE :drinking party
DETAILS :Ginza 19:00
FINISHED : false
2017-03-02 22:37:28.390 INFO 86040 --- [ main] c.e.MybatisKotlinDemoApplicationKt : Started MybatisKotlinDemoApplicationKt in 2.282 seconds (JVM running for 2.677)
...
Even if I can't completely migrate from Java to Kotlin, I personally think that the option of using Kotlin, which only supports multi-line strings in the Mapper interface, is quite "ant". I thought it was a pity that the actual argument name could not be handled as a bind variable name in Kotlin 1.0, but since it will be possible to handle it perfectly from Kotlin 1.1, MyBatis is annotated (specify SQL with annotation) I think it's worth a try if you're using it in).
For the compilation method using kotlin-maven-plugin when Java and Kotlin coexist, Kotlin reference page .html # compiling-kotlin-and-java-sources).
Recommended Posts