├── .github
└── workflows
│ └── main.yml
├── .gitignore
├── .travis.yml
├── LICENSE
├── build.gradle
├── gradle.tar
├── gradle.tar.enc
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── readme.md
├── settings.gradle
└── src
├── main
└── kotlin
│ └── io
│ └── wkz
│ └── kotlin
│ └── mybatis
│ ├── JsonArrayTypeHandler.kt
│ ├── JsonListTypeHandler.kt
│ ├── JsonObjectTypeHandler.kt
│ └── MyBatisObjectMapper.kt
└── test
├── kotlin
└── io
│ └── wkz
│ └── kotlin
│ └── mybatis
│ ├── JsonArrayTypeHandlerTest.kt
│ ├── JsonListTypeHandlerTest.kt
│ ├── JsonObjectTypeHandlerTest.kt
│ ├── MyBatisObjectMapperTest.kt
│ ├── MybatisScanConfiguration.kt
│ ├── dao
│ ├── ArrayJsonDao.kt
│ ├── ListJsonDao.kt
│ └── ObjectJsonDao.kt
│ └── entity
│ └── Entity.kt
└── resources
├── application.yaml
└── sqlmap
├── mappers
├── ArrayJsonDao.xml
├── ListJsonDao.xml
└── ObjectJsonDao.xml
└── test.xml
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | name: Build
2 | on:
3 | push:
4 | branches:
5 | - master
6 | pull_request:
7 | types: [opened, synchronize, reopened]
8 | jobs:
9 | build:
10 | name: Build
11 | runs-on: ubuntu-latest
12 | steps:
13 | - uses: actions/checkout@v2
14 | with:
15 | fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
16 | - name: Set up JDK 11
17 | uses: actions/setup-java@v1
18 | with:
19 | java-version: 11
20 | - name: Cache SonarCloud packages
21 | uses: actions/cache@v1
22 | with:
23 | path: ~/.sonar/cache
24 | key: ${{ runner.os }}-sonar
25 | restore-keys: ${{ runner.os }}-sonar
26 | - name: Cache Gradle packages
27 | uses: actions/cache@v1
28 | with:
29 | path: ~/.gradle/caches
30 | key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}
31 | restore-keys: ${{ runner.os }}-gradle
32 | - name: Start MySQL
33 | run: sudo systemctl start mysql.service
34 | - name: Build and analyze
35 | env:
36 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
37 | SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
38 | run: ./gradlew build sonarqube --info
39 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by .ignore support plugin (hsz.mobi)
2 | ### Gradle template
3 | .gradle
4 | /build/
5 |
6 | # Ignore Gradle GUI config
7 | gradle-app.setting
8 |
9 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
10 |
11 |
12 | # Cache of project
13 | .gradletasknamecache
14 |
15 | # # Work around https://youtrack.jetbrains.com/issue/IDEA-116898
16 | # gradle/wrapper/gradle-wrapper.properties
17 | ### Kotlin template
18 | # Compiled class file
19 | *.class
20 |
21 | # Log file
22 | *.log
23 |
24 | # BlueJ files
25 | *.ctxt
26 |
27 | # Mobile Tools for Java (J2ME)
28 | .mtj.tmp/
29 |
30 | # Package Files #
31 | *.jar
32 | !gradle-wrapper.jar
33 | *.war
34 | *.ear
35 | *.zip
36 | *.tar.gz
37 | *.rar
38 |
39 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
40 | hs_err_pid*
41 | out/
42 | .idea/
43 | mybatis-json-typehandler.iml
44 |
45 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: java
2 | services: mysql
3 | before_install:
4 | - openssl aes-256-cbc -K $encrypted_0b8355631cb2_key -iv $encrypted_0b8355631cb2_iv
5 | -in gradle.tar.enc -out gradle.tar -d
6 | - tar xvf gradle.tar
7 | - mysql -e "create database if not exists test CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
8 | use test;
9 | drop table if exists list_json_tbl;
10 | create table list_json_tbl(
11 | id int
12 | unsigned primary key unique auto_increment,
13 | listJson varchar(255) not null
14 | )
15 | ENGINE = InnoDB
16 | DEFAULT CHARSET = utf8mb4
17 | COLLATE utf8mb4_general_ci;
18 | insert into list_json_tbl
19 | (listJson)
20 | values (''),
21 | ('[{\"name\":\"测试\",\"age\":13},{\"name\":\"测试2\",\"age\":14}]');
22 | drop table if exists object_json_tbl;
23 | create table object_json_tbl
24 | (
25 | id int
26 | unsigned primary key unique auto_increment,
27 | objectJson varchar(255) not null
28 | )
29 | ENGINE = InnoDB
30 | DEFAULT CHARSET = utf8mb4
31 | COLLATE utf8mb4_general_ci;
32 | insert into object_json_tbl
33 | (objectJson)
34 | values (''),
35 | ('{\"name\":\"测试\",\"age\":13}');
36 | drop table if exists array_json_tbl;
37 | create table array_json_tbl
38 | (
39 | id int unsigned primary key unique auto_increment,
40 | arrayJson varchar(255) not null
41 | )
42 | engine = InnoDB
43 | default charset = utf8mb4
44 | collate utf8mb4_general_ci;
45 | insert into array_json_tbl (arrayJson)
46 | values (''),
47 | ('[{\"name\":\"测试\",\"age\":13},{\"name\":\"测试2\",\"age\":14}]');"
48 | after_success:
49 | - bash <(curl -s https://codecov.io/bash)
50 | before_cache:
51 | - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
52 | - rm -fr $HOME/.gradle/caches/*/plugin-resolution/
53 | cache:
54 | directories:
55 | - "$HOME/.gradle/caches/"
56 | - "$HOME/.gradle/wrapper/"
57 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Tyrael
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | ext {
3 | kotlin_version = '1.3.50'
4 | scm_url = 'https://github.com/wangkezun/mybatis-json-typehandler'
5 | scm_connection = 'scm:git:git@github.com:wangkezun/mybatis-json-typehandler.git'
6 | scm_developerConnection = 'scm:git:git@github.com:wangkezun/mybatis-json-typehandler.git'
7 | scm_tag = 'HEAD'
8 | issueUrl = 'https://github.com/wangkezun/mybatis-json-typehandler/issues'
9 | }
10 |
11 | repositories {
12 | mavenCentral()
13 | jcenter()
14 | }
15 | }
16 |
17 | plugins {
18 | id "org.jetbrains.kotlin.jvm" version "1.3.50"
19 | id 'jacoco'
20 | id 'maven-publish'
21 | id 'maven'
22 | id 'signing'
23 | id 'org.jetbrains.dokka' version "0.10.0"
24 | id "org.sonarqube" version "3.4.0.2513"
25 | }
26 |
27 |
28 | group = 'io.wkz.kotlin'
29 | version = '1.0.2'
30 |
31 | repositories {
32 | mavenCentral()
33 | jcenter()
34 | }
35 |
36 | dependencies {
37 | compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
38 | compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
39 | compile group: 'org.mybatis', name: 'mybatis', version: '3.5.6'
40 | compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.12.6.1'
41 | compile group: 'com.fasterxml.jackson.module', name: 'jackson-module-kotlin', version: '2.9.7'
42 | testCompile group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: '5.3.1'
43 | testCompile group: 'org.springframework.boot', name: 'spring-boot-starter-test', version: '2.0.6.RELEASE'
44 | testCompile group: 'mysql', name: 'mysql-connector-java', version: '8.0.13'
45 | testCompile group: 'org.mybatis.spring.boot', name: 'mybatis-spring-boot-starter', version: '1.3.2'
46 | testCompile group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: '5.3.1'
47 | }
48 |
49 | jacocoTestReport {
50 | reports {
51 | xml.enabled = true
52 | html.enabled = false
53 | }
54 | }
55 |
56 | compileKotlin {
57 | kotlinOptions.jvmTarget = "1.8"
58 | }
59 | compileTestKotlin {
60 | kotlinOptions.jvmTarget = "1.8"
61 | }
62 | test {
63 | useJUnitPlatform()
64 | }
65 |
66 | // build.gradle
67 | task sourceJar(type: Jar) {
68 | from sourceSets.main.allSource
69 | }
70 |
71 | check.dependsOn jacocoTestReport
72 |
73 | dokka {
74 | outputFormat = 'javadoc'
75 | outputDirectory = javadoc.destinationDir
76 | inputs.dir 'src/main/kotlin'
77 | cacheRoot = 'default'
78 | }
79 |
80 | task packageJavadoc(type: Jar, dependsOn: dokka) {
81 | classifier = 'javadoc'
82 | from javadoc.destinationDir
83 | }
84 |
85 | publishing {
86 | publications {
87 | mavenJava(MavenPublication) {
88 | from components.java
89 | pom {
90 | name = 'mybatis-json-typehandler'
91 | url = 'https://github.com/wangkezun/mybatis-json-typehandler'
92 | description = 'A Mybatis TypeHandler for json object and json array'
93 | scm {
94 | url = scm_url
95 | connection = scm_connection
96 | developerConnection = scm_developerConnection
97 | tag = scm_tag
98 | }
99 |
100 | license {
101 | name = 'MIT Licence'
102 | url = 'https://raw.githubusercontent.com/wangkezun/mybatis-json-typehandler/master/LICENSE'
103 | distribution = 'repo'
104 | }
105 | developers {
106 | developer {
107 | id= 'wangkezun'
108 | name = 'Wang Kezun'
109 | email = 'wangkezun@gmail.com'
110 | }
111 | }
112 | issueManagement {
113 | system = 'GitHub Issues'
114 | url = issueUrl
115 | }
116 | }
117 | artifact sourceJar {
118 | classifier "sources"
119 | }
120 | artifact packageJavadoc {
121 | classifier "javadoc"
122 | }
123 | }
124 | }
125 | repositories {
126 | maven {
127 | if (project.version.endsWith('-SNAPSHOT')) {
128 | url = "https://oss.sonatype.org/content/repositories/snapshots"
129 | } else {
130 | url = "https://oss.sonatype.org/service/local/staging/deploy/maven2/"
131 | }
132 | credentials {
133 | username findProperty("ossrhUsername") ?: System.getenv("OSSRH_USERNAME")
134 | password findProperty("ossrhPassword") ?: System.getenv("OSSRH_PASSWORD")
135 | }
136 | }
137 | }
138 | }
139 | signing {
140 | required { gradle.taskGraph.hasTask("publishing") }
141 | sign publishing.publications.mavenJava
142 | }
143 | sonarqube {
144 | properties {
145 | property "sonar.projectKey", "wangkezun_mybatis-json-typehandler"
146 | property "sonar.organization", "wangkezun"
147 | property "sonar.host.url", "https://sonarcloud.io"
148 | }
149 | }
150 |
--------------------------------------------------------------------------------
/gradle.tar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangkezun/mybatis-json-typehandler/d6bfbcd1d8ee4e16bd012379d92a9d7350a71337/gradle.tar
--------------------------------------------------------------------------------
/gradle.tar.enc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangkezun/mybatis-json-typehandler/d6bfbcd1d8ee4e16bd012379d92a9d7350a71337/gradle.tar.enc
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangkezun/mybatis-json-typehandler/d6bfbcd1d8ee4e16bd012379d92a9d7350a71337/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Sun Oct 20 17:32:34 CST 2019
2 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.3-all.zip
3 | distributionBase=GRADLE_USER_HOME
4 | distributionPath=wrapper/dists
5 | zipStorePath=wrapper/dists
6 | zipStoreBase=GRADLE_USER_HOME
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | #
4 | # Copyright 2015 the original author or authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | ##
21 | ## Gradle start up script for UN*X
22 | ##
23 | ##############################################################################
24 |
25 | # Attempt to set APP_HOME
26 | # Resolve links: $0 may be a link
27 | PRG="$0"
28 | # Need this for relative symlinks.
29 | while [ -h "$PRG" ] ; do
30 | ls=`ls -ld "$PRG"`
31 | link=`expr "$ls" : '.*-> \(.*\)$'`
32 | if expr "$link" : '/.*' > /dev/null; then
33 | PRG="$link"
34 | else
35 | PRG=`dirname "$PRG"`"/$link"
36 | fi
37 | done
38 | SAVED="`pwd`"
39 | cd "`dirname \"$PRG\"`/" >/dev/null
40 | APP_HOME="`pwd -P`"
41 | cd "$SAVED" >/dev/null
42 |
43 | APP_NAME="Gradle"
44 | APP_BASE_NAME=`basename "$0"`
45 |
46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
48 |
49 | # Use the maximum available, or set MAX_FD != -1 to use that value.
50 | MAX_FD="maximum"
51 |
52 | warn () {
53 | echo "$*"
54 | }
55 |
56 | die () {
57 | echo
58 | echo "$*"
59 | echo
60 | exit 1
61 | }
62 |
63 | # OS specific support (must be 'true' or 'false').
64 | cygwin=false
65 | msys=false
66 | darwin=false
67 | nonstop=false
68 | case "`uname`" in
69 | CYGWIN* )
70 | cygwin=true
71 | ;;
72 | Darwin* )
73 | darwin=true
74 | ;;
75 | MINGW* )
76 | msys=true
77 | ;;
78 | NONSTOP* )
79 | nonstop=true
80 | ;;
81 | esac
82 |
83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
84 |
85 | # Determine the Java command to use to start the JVM.
86 | if [ -n "$JAVA_HOME" ] ; then
87 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
88 | # IBM's JDK on AIX uses strange locations for the executables
89 | JAVACMD="$JAVA_HOME/jre/sh/java"
90 | else
91 | JAVACMD="$JAVA_HOME/bin/java"
92 | fi
93 | if [ ! -x "$JAVACMD" ] ; then
94 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
95 |
96 | Please set the JAVA_HOME variable in your environment to match the
97 | location of your Java installation."
98 | fi
99 | else
100 | JAVACMD="java"
101 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
102 |
103 | Please set the JAVA_HOME variable in your environment to match the
104 | location of your Java installation."
105 | fi
106 |
107 | # Increase the maximum file descriptors if we can.
108 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
109 | MAX_FD_LIMIT=`ulimit -H -n`
110 | if [ $? -eq 0 ] ; then
111 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
112 | MAX_FD="$MAX_FD_LIMIT"
113 | fi
114 | ulimit -n $MAX_FD
115 | if [ $? -ne 0 ] ; then
116 | warn "Could not set maximum file descriptor limit: $MAX_FD"
117 | fi
118 | else
119 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
120 | fi
121 | fi
122 |
123 | # For Darwin, add options to specify how the application appears in the dock
124 | if $darwin; then
125 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
126 | fi
127 |
128 | # For Cygwin or MSYS, switch paths to Windows format before running java
129 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
130 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
131 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
132 | JAVACMD=`cygpath --unix "$JAVACMD"`
133 |
134 | # We build the pattern for arguments to be converted via cygpath
135 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
136 | SEP=""
137 | for dir in $ROOTDIRSRAW ; do
138 | ROOTDIRS="$ROOTDIRS$SEP$dir"
139 | SEP="|"
140 | done
141 | OURCYGPATTERN="(^($ROOTDIRS))"
142 | # Add a user-defined pattern to the cygpath arguments
143 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
144 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
145 | fi
146 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
147 | i=0
148 | for arg in "$@" ; do
149 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
150 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
151 |
152 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
153 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
154 | else
155 | eval `echo args$i`="\"$arg\""
156 | fi
157 | i=$((i+1))
158 | done
159 | case $i in
160 | (0) set -- ;;
161 | (1) set -- "$args0" ;;
162 | (2) set -- "$args0" "$args1" ;;
163 | (3) set -- "$args0" "$args1" "$args2" ;;
164 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
165 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
166 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
167 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
168 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
169 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
170 | esac
171 | fi
172 |
173 | # Escape application args
174 | save () {
175 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
176 | echo " "
177 | }
178 | APP_ARGS=$(save "$@")
179 |
180 | # Collect all arguments for the java command, following the shell quoting and substitution rules
181 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
182 |
183 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
184 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
185 | cd "$(dirname "$0")"
186 | fi
187 |
188 | exec "$JAVACMD" "$@"
189 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
33 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
34 |
35 | @rem Find java.exe
36 | if defined JAVA_HOME goto findJavaFromJavaHome
37 |
38 | set JAVA_EXE=java.exe
39 | %JAVA_EXE% -version >NUL 2>&1
40 | if "%ERRORLEVEL%" == "0" goto init
41 |
42 | echo.
43 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
44 | echo.
45 | echo Please set the JAVA_HOME variable in your environment to match the
46 | echo location of your Java installation.
47 |
48 | goto fail
49 |
50 | :findJavaFromJavaHome
51 | set JAVA_HOME=%JAVA_HOME:"=%
52 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
53 |
54 | if exist "%JAVA_EXE%" goto init
55 |
56 | echo.
57 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
58 | echo.
59 | echo Please set the JAVA_HOME variable in your environment to match the
60 | echo location of your Java installation.
61 |
62 | goto fail
63 |
64 | :init
65 | @rem Get command-line arguments, handling Windows variants
66 |
67 | if not "%OS%" == "Windows_NT" goto win9xME_args
68 |
69 | :win9xME_args
70 | @rem Slurp the command line arguments.
71 | set CMD_LINE_ARGS=
72 | set _SKIP=2
73 |
74 | :win9xME_args_slurp
75 | if "x%~1" == "x" goto execute
76 |
77 | set CMD_LINE_ARGS=%*
78 |
79 | :execute
80 | @rem Setup the command line
81 |
82 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
83 |
84 | @rem Execute Gradle
85 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
86 |
87 | :end
88 | @rem End local scope for the variables with windows NT shell
89 | if "%ERRORLEVEL%"=="0" goto mainEnd
90 |
91 | :fail
92 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
93 | rem the _cmd.exe /c_ return code!
94 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
95 | exit /b 1
96 |
97 | :mainEnd
98 | if "%OS%"=="Windows_NT" endlocal
99 |
100 | :omega
101 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # Mybatis-Json-TypeHandler [](https://travis-ci.org/wangkezun/mybatis-json-typehandler) [](https://github.com/wangkezun/mybatis-json-typehandler) [](https://github.com/wangkezun/mybatis-json-typehandler/blob/master/LICENSE)[](https://depshield.github.io)
2 |
3 | ---
4 |
5 | ## 目的
6 | 开发过程中经常会遇到一对多的关系,大部分情况下这种关系都存在一张表中,通过id等关系进行关联。
7 | 但是在某些特殊情况下,单独为这种情况生成一个表并不是非常必须,而且也不会对这种关系进行查询。
8 | 此时可以考虑将数据存在一对多的一这个表中,把多的数据存成JSON结构。
9 | 但是MyBatis并没有对这种情况提供原生支持。此项目提供了一种自动序列化与反序列化的功能。
10 | 调用时仅需要在mapper中配置好即可使用。
11 |
12 | ## 依赖
13 | 项目依赖于MyBatis、Jackson。基于Kotlin语言。java8+
14 |
15 | ## 用法
16 | 1. 引入依赖
17 | * maven
18 | ```xml
19 |
20 | io.wkz.kotlin
21 | mybatis-json-typehandler
22 | 1.0.1
23 |
24 | ```
25 |
26 | * gradle
27 | ```groovy
28 | compile 'io.wkz.kotlin:mybatis-json-typehandler:1.0.1'
29 | ```
30 | 1. 实体类
31 |
32 | 与正常的实体类没有任何区别
33 |
34 | ```java
35 | public class Data {
36 | private int id;
37 | //数据库中序列化为JSON Object
38 | private JsonObject targetObject;
39 | // 数据库中序列化为JSON Array
40 | private List targetList;
41 | //数据库中序列化为JSON Array
42 | private JsonObject[] tartetArray;
43 | }
44 | public class JsonObject {
45 | private String xxx;
46 | private int yyy;
47 | }
48 | ```
49 | ```kotlin
50 | data class Data(val id: Int = 0, val targetObject: JsonObject? = null, val targetList:List? =null, val targetArray:Array? = null)
51 | data class JsonObject(val xxx:String, val yyy:Int)
52 | ```
53 | 2. mapper
54 |
55 | 重点修改在#{}以及resultMap的result中。
56 | 明确定义javaType以及typeHandler即可,如下所示
57 | ```xml
58 |
61 |
62 |
63 |
65 |
67 |
69 |
70 |
71 | insert into tbl_name (targetObject,targetList) value
72 | (#{targetObject,javaType=JsonObject,jdbcType=VARCHAR,typeHandler=io.wkz.kotlin.mybatis.JsonObjectTypeHandler},
73 | #{targetList,javaType=JsonObject,jdbcType=VARCHAR,typeHandler=io.wkz.kotlin.mybatis.JsonListTypeHandler},
74 | #{targetArray,javaType=JsonObject,jdbcType=VARCHAR,typeHandler=io.wkz.kotlin.mybatis.JsonArrayTypeHandler},
75 | )
76 |
77 |
82 |
83 | ```
84 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name = 'mybatis-json-typehandler'
2 |
3 |
--------------------------------------------------------------------------------
/src/main/kotlin/io/wkz/kotlin/mybatis/JsonArrayTypeHandler.kt:
--------------------------------------------------------------------------------
1 | package io.wkz.kotlin.mybatis
2 |
3 | import com.fasterxml.jackson.databind.ObjectReader
4 | import com.fasterxml.jackson.databind.ObjectWriter
5 | import org.apache.ibatis.type.BaseTypeHandler
6 | import org.apache.ibatis.type.JdbcType
7 | import org.apache.ibatis.type.MappedJdbcTypes
8 | import java.sql.CallableStatement
9 | import java.sql.PreparedStatement
10 | import java.sql.ResultSet
11 | import java.sql.SQLException
12 |
13 | /**
14 | * 针对object的typeHandler。
15 | *
16 | * @author wangkezun(wangkezun@gmail.com)
17 | * *
18 | * @since 1.0
19 | * @param clazz 需要进行转换的java类
20 | */
21 | @MappedJdbcTypes(JdbcType.VARCHAR)
22 | class JsonArrayTypeHandler(clazz: Class) : BaseTypeHandler>() {
23 | private val arrayReader: ObjectReader
24 | private val arrayWriter: ObjectWriter
25 |
26 | init {
27 | val objectMapper = MyBatisObjectMapper.objectMapper
28 | val type = objectMapper.typeFactory.constructArrayType(clazz)
29 | arrayReader = objectMapper.readerFor(type)
30 | arrayWriter = objectMapper.writerFor(type)
31 | }
32 |
33 | /**
34 | * json 转换成对象
35 | */
36 | private fun jsonToObject(json: String?): Array? {
37 | return if (!json.isNullOrBlank()) {
38 | arrayReader.readValue(json)
39 | } else {
40 | null
41 | }
42 | }
43 |
44 | @Throws(SQLException::class)
45 | override fun setNonNullParameter(ps: PreparedStatement,
46 | i: Int,
47 | parameter: Array?,
48 | jdbcType: JdbcType) {
49 |
50 | ps.setString(i, arrayWriter.writeValueAsString(parameter))
51 | }
52 |
53 | @Throws(SQLException::class)
54 | override fun getNullableResult(cs: CallableStatement, columnIndex: Int): Array? {
55 | val json = cs.getString(columnIndex)
56 |
57 | return jsonToObject(json)
58 | }
59 |
60 | @Throws(SQLException::class)
61 | override fun getNullableResult(rs: ResultSet, columnIndex: Int): Array? {
62 | val json = rs.getString(columnIndex)
63 |
64 | return jsonToObject(json)
65 | }
66 |
67 | @Throws(SQLException::class)
68 | override fun getNullableResult(rs: ResultSet, columnName: String): Array? {
69 | val json = rs.getString(columnName)
70 |
71 | return jsonToObject(json)
72 | }
73 |
74 | override fun setParameter(ps: PreparedStatement?, i: Int, parameter: Array?, jdbcType: JdbcType?) {
75 | if (parameter == null) {
76 | ps?.setString(i, "[]")
77 | } else {
78 | super.setParameter(ps, i, parameter, jdbcType)
79 | }
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/src/main/kotlin/io/wkz/kotlin/mybatis/JsonListTypeHandler.kt:
--------------------------------------------------------------------------------
1 | package io.wkz.kotlin.mybatis
2 |
3 | import com.fasterxml.jackson.databind.ObjectReader
4 | import com.fasterxml.jackson.databind.ObjectWriter
5 | import org.apache.ibatis.type.BaseTypeHandler
6 | import org.apache.ibatis.type.JdbcType
7 | import org.apache.ibatis.type.MappedJdbcTypes
8 | import java.sql.CallableStatement
9 | import java.sql.PreparedStatement
10 | import java.sql.ResultSet
11 | import java.sql.SQLException
12 |
13 | /**
14 | *
15 | * @author wangkezun(wangkezun@gmail.com)
16 | * @since 1.0
17 | */
18 | @MappedJdbcTypes(JdbcType.VARCHAR)
19 | class JsonListTypeHandler(clazz: Class) : BaseTypeHandler>() {
20 | private val listReader: ObjectReader
21 | private val listWriter: ObjectWriter
22 |
23 |
24 | init {
25 | val objectMapper = MyBatisObjectMapper.objectMapper
26 | val type = objectMapper.typeFactory.constructCollectionType(List::class.java, clazz)
27 | listReader = objectMapper.readerFor(type)
28 | listWriter = objectMapper.writerFor(type)
29 | }
30 |
31 | /**
32 | * json 转换成对象
33 | */
34 | private fun jsonToList(json: String?): List? {
35 | return if (!json.isNullOrBlank()) {
36 | listReader.readValue(json)
37 | } else{
38 | emptyList()
39 | }
40 |
41 | }
42 |
43 | @Throws(SQLException::class)
44 | override fun setNonNullParameter(ps: PreparedStatement,
45 | i: Int,
46 | parameter: List?,
47 | jdbcType: JdbcType) {
48 |
49 | ps.setString(i, listWriter.writeValueAsString(parameter))
50 | }
51 |
52 | @Throws(SQLException::class)
53 | override fun getNullableResult(cs: CallableStatement, columnIndex: Int): List? {
54 | val json = cs.getString(columnIndex)
55 |
56 | return jsonToList(json)
57 | }
58 |
59 | @Throws(SQLException::class)
60 | override fun getNullableResult(rs: ResultSet, columnIndex: Int): List? {
61 | val json = rs.getString(columnIndex)
62 |
63 | return jsonToList(json)
64 | }
65 |
66 | @Throws(SQLException::class)
67 | override fun getNullableResult(rs: ResultSet, columnName: String): List? {
68 | val json = rs.getString(columnName)
69 |
70 | return jsonToList(json)
71 | }
72 |
73 | override fun setParameter(ps: PreparedStatement?, i: Int, parameter: List?, jdbcType: JdbcType?) {
74 | if (parameter == null) {
75 | ps?.setString(i, "[]")
76 | } else {
77 | super.setParameter(ps, i, parameter, jdbcType)
78 | }
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/src/main/kotlin/io/wkz/kotlin/mybatis/JsonObjectTypeHandler.kt:
--------------------------------------------------------------------------------
1 | package io.wkz.kotlin.mybatis
2 |
3 | import org.apache.ibatis.type.BaseTypeHandler
4 | import org.apache.ibatis.type.JdbcType
5 | import org.apache.ibatis.type.MappedJdbcTypes
6 | import java.sql.CallableStatement
7 | import java.sql.PreparedStatement
8 | import java.sql.ResultSet
9 | import java.sql.SQLException
10 |
11 | /**
12 | * 针对object的typeHandler。
13 | *
14 | * @author wangkezun(wangkezun@gmail.com)
15 | * *
16 | * @since 1.0
17 | * @param clazz 需要进行转换的java类
18 | */
19 | @MappedJdbcTypes(JdbcType.VARCHAR)
20 | class JsonObjectTypeHandler(clazz: Class) : BaseTypeHandler() {
21 | private val objectReader = MyBatisObjectMapper.objectMapper.readerFor(clazz)
22 | private val objectWriter = MyBatisObjectMapper.objectMapper.writerFor(clazz)
23 |
24 | /**
25 | * json 转换成对象
26 | */
27 | private fun jsonToObject(json: String?): Any? {
28 | return if (!json.isNullOrBlank()) {
29 | objectReader.readValue(json)
30 | } else {
31 | null
32 | }
33 | }
34 |
35 | @Throws(SQLException::class)
36 | override fun setNonNullParameter(ps: PreparedStatement,
37 | i: Int,
38 | parameter: Any?,
39 | jdbcType: JdbcType) {
40 |
41 | ps.setString(i, objectWriter.writeValueAsString(parameter))
42 | }
43 |
44 | @Throws(SQLException::class)
45 | override fun getNullableResult(cs: CallableStatement, columnIndex: Int): Any? {
46 | val json = cs.getString(columnIndex)
47 |
48 | return jsonToObject(json)
49 | }
50 |
51 | @Throws(SQLException::class)
52 | override fun getNullableResult(rs: ResultSet, columnIndex: Int): Any? {
53 | val json = rs.getString(columnIndex)
54 |
55 | return jsonToObject(json)
56 | }
57 |
58 | @Throws(SQLException::class)
59 | override fun getNullableResult(rs: ResultSet, columnName: String): Any? {
60 | val json = rs.getString(columnName)
61 |
62 | return jsonToObject(json)
63 | }
64 |
65 | override fun setParameter(ps: PreparedStatement?, i: Int, parameter: Any, jdbcType: JdbcType?) {
66 | if (parameter == null) {
67 | ps?.setString(i, "")
68 | } else {
69 | super.setParameter(ps, i, parameter, jdbcType)
70 | }
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/src/main/kotlin/io/wkz/kotlin/mybatis/MyBatisObjectMapper.kt:
--------------------------------------------------------------------------------
1 | package io.wkz.kotlin.mybatis
2 |
3 | import com.fasterxml.jackson.databind.ObjectMapper
4 | import com.fasterxml.jackson.module.kotlin.KotlinModule
5 |
6 | /**
7 | * This class generate a [ObjectMapper] to serialize or deserialize object or list.
8 | * TypeHandler don't use it directly,
9 | * but use it to create [com.fasterxml.jackson.databind.ObjectReader] and
10 | * [com.fasterxml.jackson.databind.ObjectWriter] to ensure thread-safe and optimize serialize or deserialize speed
11 | * @author wangkezun(wangkezun@gmail.com)
12 | * @since 1.0
13 | */
14 | internal object MyBatisObjectMapper {
15 |
16 | val objectMapper = ObjectMapper().apply{
17 | // You could change some config in this block like this
18 | //this.disable(com.fasterxml.jackson.databind.SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
19 | this.registerModule(KotlinModule())
20 | }
21 |
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/src/test/kotlin/io/wkz/kotlin/mybatis/JsonArrayTypeHandlerTest.kt:
--------------------------------------------------------------------------------
1 | package io.wkz.kotlin.mybatis
2 |
3 | import io.wkz.kotlin.mybatis.dao.ArrayJsonDao
4 | import io.wkz.kotlin.mybatis.entity.ArrayJson
5 | import io.wkz.kotlin.mybatis.entity.SubObject
6 | import org.junit.jupiter.api.Assertions.*
7 | import org.junit.jupiter.api.DisplayName
8 | import org.junit.jupiter.api.Test
9 | import org.junit.jupiter.api.extension.ExtendWith
10 | import org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration
11 | import org.springframework.beans.factory.annotation.Autowired
12 | import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
13 | import org.springframework.boot.test.context.SpringBootTest
14 | import org.springframework.test.context.junit.jupiter.SpringExtension
15 |
16 | /**
17 | *
18 | * @author 王可尊
19 | * @since 1.0
20 | */
21 | @DisplayName("Test JsonArrayTypeHandler")
22 | @ExtendWith(SpringExtension::class)
23 | @SpringBootTest(classes = [DataSourceAutoConfiguration::class, MybatisAutoConfiguration::class, MybatisScanConfiguration::class])
24 | class JsonArrayTypeHandlerTest {
25 |
26 | @Autowired
27 | private lateinit var arrayJsonDao: ArrayJsonDao
28 |
29 | @Test
30 | fun testInsertJsonListAsVarchar() {
31 | val emptyObject = ArrayJson()
32 | arrayJsonDao.add(emptyObject)
33 | assertNotEquals(0, emptyObject.id)
34 | val notEmptyObject = ArrayJson(arrayJson = arrayOf(SubObject("新增", 14), SubObject("新增2", 15)))
35 | arrayJsonDao.add(notEmptyObject)
36 | assertNotEquals(0, emptyObject.id)
37 | }
38 |
39 | @Test
40 | fun testGetJsonListFromVarchar() {
41 | val emptyListResult = arrayJsonDao.get(1)
42 | assertNotNull(emptyListResult)
43 | assertEquals(1, emptyListResult.id)
44 | println(emptyListResult)
45 | assertNull(emptyListResult.arrayJson)
46 |
47 | val notEmptyListResult = arrayJsonDao.get(2)
48 | assertNotNull(notEmptyListResult)
49 | val (id, listJson) = notEmptyListResult
50 | assertEquals(2, id)
51 | assertNotNull(listJson)
52 | assertEquals(2, listJson!!.size)
53 | assertEquals(SubObject("测试", 13), listJson[0])
54 | assertEquals(SubObject("测试2", 14), listJson[1])
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/test/kotlin/io/wkz/kotlin/mybatis/JsonListTypeHandlerTest.kt:
--------------------------------------------------------------------------------
1 | package io.wkz.kotlin.mybatis
2 |
3 | import io.wkz.kotlin.mybatis.dao.ListJsonDao
4 | import io.wkz.kotlin.mybatis.entity.ListJson
5 | import io.wkz.kotlin.mybatis.entity.SubObject
6 | import org.junit.jupiter.api.Assertions.*
7 | import org.junit.jupiter.api.DisplayName
8 | import org.junit.jupiter.api.Test
9 | import org.junit.jupiter.api.extension.ExtendWith
10 | import org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration
11 | import org.springframework.beans.factory.annotation.Autowired
12 | import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
13 | import org.springframework.boot.test.context.SpringBootTest
14 | import org.springframework.test.context.junit.jupiter.SpringExtension
15 |
16 | /**
17 | *
18 | * @author 王可尊
19 | * @since 1.0
20 | */
21 | @DisplayName("Test JsonListTypeHandler")
22 | @ExtendWith(SpringExtension::class)
23 | @SpringBootTest(classes = [DataSourceAutoConfiguration::class, MybatisAutoConfiguration::class, MybatisScanConfiguration::class])
24 | class JsonListTypeHandlerTest {
25 |
26 | @Autowired
27 | private lateinit var listJsonDao: ListJsonDao
28 |
29 | @Test
30 | fun testInsertJsonListAsVarchar() {
31 | val emptyObject = ListJson()
32 | listJsonDao.add(emptyObject)
33 | assertNotEquals(0, emptyObject.id)
34 | val notEmptyObject = ListJson(listJson = listOf(SubObject("新增", 14), SubObject("新增2", 15)))
35 | listJsonDao.add(notEmptyObject)
36 | assertNotEquals(0, emptyObject.id)
37 | }
38 |
39 | @Test
40 | fun testGetJsonListFromVarchar() {
41 | val emptyListResult = listJsonDao.get(1)
42 | assertNotNull(emptyListResult)
43 | assertEquals(1, emptyListResult.id)
44 | println(emptyListResult)
45 | assertNotNull(emptyListResult.listJson)
46 | assertEquals(0, emptyListResult.listJson!!.size)
47 |
48 | val notEmptyListResult = listJsonDao.get(2)
49 | assertNotNull(notEmptyListResult)
50 | val (id, listJson) = notEmptyListResult
51 | assertEquals(2, id)
52 | assertNotNull(listJson)
53 | assertEquals(2, listJson!!.size)
54 | assertEquals(SubObject("测试", 13), listJson[0])
55 | assertEquals(SubObject("测试2", 14), listJson[1])
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/test/kotlin/io/wkz/kotlin/mybatis/JsonObjectTypeHandlerTest.kt:
--------------------------------------------------------------------------------
1 | package io.wkz.kotlin.mybatis
2 |
3 | import io.wkz.kotlin.mybatis.dao.ObjectJsonDao
4 | import io.wkz.kotlin.mybatis.entity.ObjectJson
5 | import io.wkz.kotlin.mybatis.entity.SubObject
6 | import org.apache.ibatis.io.Resources
7 | import org.apache.ibatis.jdbc.ScriptRunner
8 | import org.apache.ibatis.session.SqlSessionFactory
9 | import org.junit.Assert.*
10 | import org.junit.BeforeClass
11 | import org.junit.jupiter.api.Assertions.assertAll
12 | import org.junit.jupiter.api.DisplayName
13 | import org.junit.jupiter.api.Test
14 | import org.junit.jupiter.api.extension.ExtendWith
15 | import org.junit.jupiter.api.function.Executable
16 | import org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration
17 | import org.springframework.beans.factory.annotation.Autowired
18 | import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
19 | import org.springframework.boot.test.context.SpringBootTest
20 | import org.springframework.test.context.junit.jupiter.SpringExtension
21 |
22 | /**
23 | *
24 | * @author 王可尊
25 | * @since 1.0
26 | */
27 | @DisplayName("Test JsonObjectTypeHandler")
28 | @ExtendWith(SpringExtension::class)
29 | @SpringBootTest(classes = [DataSourceAutoConfiguration::class, MybatisAutoConfiguration::class, MybatisScanConfiguration::class])
30 | internal class JsonObjectTypeHandlerTest {
31 | @Autowired
32 | private lateinit var objectJsonDao: ObjectJsonDao
33 |
34 | @Test
35 | fun testInsertJsonObjectAsVarchar() {
36 | val notEmptyObjectJson = ObjectJson(objectJson = SubObject("测试", 13))
37 | objectJsonDao.add(notEmptyObjectJson)
38 | assertNotEquals(0, notEmptyObjectJson.id)
39 | val emptyObjectJson = ObjectJson()
40 | objectJsonDao.add(emptyObjectJson)
41 | assertNotEquals(0, emptyObjectJson.id)
42 | }
43 |
44 | @Test
45 | fun testGetJsonObjectFromVarchar() {
46 | val emptyObject = objectJsonDao.get(1)
47 | assertAll(
48 | Executable { assertNotNull(emptyObject) },
49 | Executable { assertEquals(1, emptyObject.id) },
50 | Executable { assertNull(emptyObject.objectJson) }
51 | )
52 | val notEmptyObject = objectJsonDao.get(2)
53 | assertAll(
54 | Executable { assertNotNull(notEmptyObject) },
55 | Executable { assertEquals(2, notEmptyObject.id) },
56 | Executable { assertNotNull(notEmptyObject.objectJson) },
57 | Executable { assertEquals("测试", notEmptyObject.objectJson!!.name) },
58 | Executable { assertEquals(13, notEmptyObject.objectJson!!.age) }
59 | )
60 |
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/test/kotlin/io/wkz/kotlin/mybatis/MyBatisObjectMapperTest.kt:
--------------------------------------------------------------------------------
1 | package io.wkz.kotlin.mybatis
2 |
3 | import org.junit.jupiter.api.Assertions.assertNotNull
4 | import org.junit.jupiter.api.DisplayName
5 | import org.junit.jupiter.api.Test
6 | import org.mybatis.spring.annotation.MapperScan
7 |
8 | /**
9 | * @author wangkezun(wangkezun@gmail.com)
10 | * @since 1.0
11 | */
12 | @DisplayName("MyBatisObjectMapper Test Cases")
13 | @MapperScan("io.wkz.kotlin.mybatis.dao")
14 | internal class MyBatisObjectMapperTest {
15 |
16 | @Test
17 | @DisplayName("Test get ObjectMapper success")
18 | fun getObjectMapper() {
19 | assertNotNull(MyBatisObjectMapper.objectMapper)
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/test/kotlin/io/wkz/kotlin/mybatis/MybatisScanConfiguration.kt:
--------------------------------------------------------------------------------
1 | package io.wkz.kotlin.mybatis
2 |
3 | import org.mybatis.spring.annotation.MapperScan
4 | import org.springframework.context.annotation.Configuration
5 |
6 | /**
7 | *
8 | * @author 王可尊
9 | * @since 1.0
10 | */
11 | @Configuration
12 | @MapperScan("io.wkz.kotlin.mybatis.dao")
13 | open class MybatisScanConfiguration {
14 | }
15 |
--------------------------------------------------------------------------------
/src/test/kotlin/io/wkz/kotlin/mybatis/dao/ArrayJsonDao.kt:
--------------------------------------------------------------------------------
1 | package io.wkz.kotlin.mybatis.dao
2 |
3 | import io.wkz.kotlin.mybatis.entity.ArrayJson
4 |
5 | /**
6 | *
7 | * @author 王可尊
8 | * @since 1.0
9 | */
10 | interface ArrayJsonDao {
11 | fun add(listJson: ArrayJson):Int
12 | fun get(id:Int):ArrayJson
13 | }
14 |
--------------------------------------------------------------------------------
/src/test/kotlin/io/wkz/kotlin/mybatis/dao/ListJsonDao.kt:
--------------------------------------------------------------------------------
1 | package io.wkz.kotlin.mybatis.dao
2 |
3 | import io.wkz.kotlin.mybatis.entity.ListJson
4 |
5 | /**
6 | *
7 | * @author 王可尊
8 | * @since 1.0
9 | */
10 | interface ListJsonDao {
11 | fun add(listJson:ListJson):Int
12 | fun get(id:Int):ListJson
13 | }
14 |
--------------------------------------------------------------------------------
/src/test/kotlin/io/wkz/kotlin/mybatis/dao/ObjectJsonDao.kt:
--------------------------------------------------------------------------------
1 | package io.wkz.kotlin.mybatis.dao
2 |
3 | import io.wkz.kotlin.mybatis.entity.ObjectJson
4 |
5 | /**
6 | *
7 | * @author 王可尊
8 | * @since 1.0
9 | */
10 | interface ObjectJsonDao {
11 | fun add(objectJson: ObjectJson):Int
12 | fun get(id:Int):ObjectJson
13 | }
14 |
--------------------------------------------------------------------------------
/src/test/kotlin/io/wkz/kotlin/mybatis/entity/Entity.kt:
--------------------------------------------------------------------------------
1 | package io.wkz.kotlin.mybatis.entity
2 |
3 | /**
4 | *
5 | * @author 王可尊
6 | * @since 1.0
7 | */
8 | data class ObjectJson(val id: Int = 0, val objectJson: SubObject? = null)
9 |
10 | data class SubObject(val name: String, val age: Int)
11 |
12 | data class ListJson(val id: Int = 0, val listJson: List? = null)
13 |
14 | data class ArrayJson(val id: Int = 0, val arrayJson: Array? = null) {
15 | override fun equals(other: Any?): Boolean {
16 | if (this === other) return true
17 | if (javaClass != other?.javaClass) return false
18 |
19 | other as ArrayJson
20 |
21 | if (id != other.id) return false
22 | if (arrayJson != null) {
23 | if (other.arrayJson == null) return false
24 | if (!arrayJson.contentEquals(other.arrayJson)) return false
25 | } else if (other.arrayJson != null) return false
26 |
27 | return true
28 | }
29 |
30 | override fun hashCode(): Int {
31 | var result = id
32 | result = 31 * result + (arrayJson?.contentHashCode() ?: 0)
33 | return result
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/test/resources/application.yaml:
--------------------------------------------------------------------------------
1 | spring:
2 | datasource:
3 | driver-class-name: com.mysql.cj.jdbc.Driver
4 | url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai&useSSL=false&allowPublicKeyRetrieval=true
5 | username: root
6 | password: root
7 | mybatis:
8 | mapper-locations: classpath:sqlmap/mappers/*.xml
9 | config-location: classpath:sqlmap/test.xml
--------------------------------------------------------------------------------
/src/test/resources/sqlmap/mappers/ArrayJsonDao.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
8 |
9 |
10 |
11 | insert into array_json_tbl (arrayJson) value
12 | (
13 | #{arrayJson,javaType=io.wkz.kotlin.mybatis.entity.SubObject,jdbcType=VARCHAR,typeHandler=io.wkz.kotlin.mybatis.JsonArrayTypeHandler})
14 |
15 |
16 |
21 |
22 |
--------------------------------------------------------------------------------
/src/test/resources/sqlmap/mappers/ListJsonDao.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
8 |
9 |
10 |
11 | insert into list_json_tbl (listJson) value
12 | (
13 | #{listJson,javaType=io.wkz.kotlin.mybatis.entity.SubObject,jdbcType=VARCHAR,typeHandler=io.wkz.kotlin.mybatis.JsonListTypeHandler})
14 |
15 |
16 |
21 |
22 |
--------------------------------------------------------------------------------
/src/test/resources/sqlmap/mappers/ObjectJsonDao.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
8 |
9 |
10 |
11 | insert into object_json_tbl (objectJson) value
12 | (
13 | #{objectJson,javaType=io.wkz.kotlin.mybatis.entity.SubObject,jdbcType=VARCHAR,typeHandler=io.wkz.kotlin.mybatis.JsonObjectTypeHandler})
14 |
15 |
16 |
21 |
22 |
--------------------------------------------------------------------------------
/src/test/resources/sqlmap/test.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------