diff --git a/documentation-website/Writerside/hi.tree b/documentation-website/Writerside/hi.tree index 0846ae10d6..c739ec8d05 100644 --- a/documentation-website/Writerside/hi.tree +++ b/documentation-website/Writerside/hi.tree @@ -8,7 +8,10 @@ - + + + + diff --git a/documentation-website/Writerside/resources/init-kotlin-gradle-app.zip b/documentation-website/Writerside/resources/init-kotlin-gradle-app.zip index 9c51303c0d..b9b136812b 100644 Binary files a/documentation-website/Writerside/resources/init-kotlin-gradle-app.zip and b/documentation-website/Writerside/resources/init-kotlin-gradle-app.zip differ diff --git a/documentation-website/Writerside/snippets/exposed-migrations/src/main/kotlin/org/example/migrations/V2__Add_primary_key.sql b/documentation-website/Writerside/snippets/exposed-migrations/src/main/kotlin/org/example/migrations/V2__Add_primary_key.sql new file mode 100644 index 0000000000..a4104770ca --- /dev/null +++ b/documentation-website/Writerside/snippets/exposed-migrations/src/main/kotlin/org/example/migrations/V2__Add_primary_key.sql @@ -0,0 +1 @@ +ALTER TABLE USERS ADD PRIMARY KEY (ID); diff --git a/documentation-website/Writerside/snippets/get-started-with-exposed-dao/README.md b/documentation-website/Writerside/snippets/get-started-with-exposed-dao/README.md new file mode 100644 index 0000000000..4b5824c32c --- /dev/null +++ b/documentation-website/Writerside/snippets/get-started-with-exposed-dao/README.md @@ -0,0 +1,21 @@ +# Get started with Exposed DAO tutorial project + +A sample Gradle/Kotlin project built by following the steps explained in +the [Get started with Exposed DAO](https://www.jetbrains.com/help/exposed/get-started-with-exposed-dao.html) +tutorial. + +## Build + +To build the application, navigate to the `snippets` folder and run the following command: + +```shell +./gradlew :get-started-with-exposed-dao:build +``` + +## Run + +To run the application, execute the following command: + +```bash +./gradlew :get-started-with-exposed-dao:run +``` diff --git a/documentation-website/Writerside/snippets/get-started-with-exposed-dao/build.gradle.kts b/documentation-website/Writerside/snippets/get-started-with-exposed-dao/build.gradle.kts new file mode 100644 index 0000000000..53e25a60df --- /dev/null +++ b/documentation-website/Writerside/snippets/get-started-with-exposed-dao/build.gradle.kts @@ -0,0 +1,53 @@ +/* + * This file was generated by the Gradle 'init' task. + * + * This generated file contains a sample Kotlin application project to get you started. + * For more details on building Java & JVM projects, please refer to https://docs.gradle.org/8.8/userguide/building_java_projects.html in the Gradle documentation. + */ + +plugins { + // Apply the org.jetbrains.kotlin.jvm Plugin to add support for Kotlin. + alias(libs.plugins.jvm) + + // Apply the application plugin to add support for building a CLI application in Java. + application +} + +repositories { + // Use Maven Central for resolving dependencies. + mavenCentral() +} + +dependencies { + // Use the Kotlin JUnit 5 integration. + testImplementation("org.jetbrains.kotlin:kotlin-test-junit5") + + // Use the JUnit 5 integration. + testImplementation(libs.junit.jupiter.engine) + + testRuntimeOnly("org.junit.platform:junit-platform-launcher") + + // This dependency is used by the application. + implementation(libs.guava) + implementation(libs.exposed.core) + implementation(libs.exposed.dao) + implementation(libs.exposed.jdbc) + implementation(libs.h2) +} + +// Apply a specific Java toolchain to ease working on different environments. +java { + toolchain { + languageVersion = JavaLanguageVersion.of(21) + } +} + +application { + // Define the main class for the application. + mainClass = "org.example.AppKt" +} + +tasks.named("test") { + // Use JUnit Platform for unit tests. + useJUnitPlatform() +} diff --git a/documentation-website/Writerside/snippets/get-started-with-exposed-dao/src/main/kotlin/org/example/App.kt b/documentation-website/Writerside/snippets/get-started-with-exposed-dao/src/main/kotlin/org/example/App.kt new file mode 100644 index 0000000000..81e3a96f38 --- /dev/null +++ b/documentation-website/Writerside/snippets/get-started-with-exposed-dao/src/main/kotlin/org/example/App.kt @@ -0,0 +1,43 @@ +package org.example + +import org.jetbrains.exposed.v1.core.StdOutSqlLogger +import org.jetbrains.exposed.v1.jdbc.Database +import org.jetbrains.exposed.v1.jdbc.SchemaUtils +import org.jetbrains.exposed.v1.jdbc.transactions.transaction + +fun main() { + Database.connect("jdbc:h2:mem:test", driver = "org.h2.Driver") + + transaction { + addLogger(StdOutSqlLogger) + + // ... + + SchemaUtils.create(Tasks) + + val task1 = Task.new { + title = "Learn Exposed DAO" + description = "Follow the DAO tutorial" + } + + val task2 = Task.new { + title = "Read The Hobbit" + description = "Read chapter one" + isCompleted = true + } + + println("Created new tasks with ids ${task1.id} and ${task2.id}") + + val completed = Task.find { Tasks.isCompleted eq true }.toList() + println("Completed tasks: ${completed.count()}") + + // Update + task1.title = "Try Exposed DAO" + task1.isCompleted = true + println("Updated task1: $task1") + + // Delete + task2.delete() + println("Remaining tasks: ${Task.all().toList()}") + } +} diff --git a/documentation-website/Writerside/snippets/get-started-with-exposed-dao/src/main/kotlin/org/example/Task.kt b/documentation-website/Writerside/snippets/get-started-with-exposed-dao/src/main/kotlin/org/example/Task.kt new file mode 100644 index 0000000000..f8f2fe2dc1 --- /dev/null +++ b/documentation-website/Writerside/snippets/get-started-with-exposed-dao/src/main/kotlin/org/example/Task.kt @@ -0,0 +1,28 @@ +package org.example + +// ... +import org.jetbrains.exposed.v1.core.dao.id.EntityID +import org.jetbrains.exposed.v1.core.dao.id.IntIdTable +import org.jetbrains.exposed.v1.dao.IntEntity +import org.jetbrains.exposed.v1.dao.IntEntityClass + +@Suppress("MagicNumber") +object Tasks : IntIdTable("tasks") { + val title = varchar("name", 128) + val description = varchar("description", 128) + val isCompleted = bool("completed").default(false) +} + +// ... + +class Task(id: EntityID) : IntEntity(id) { + companion object : IntEntityClass(Tasks) + + var title by Tasks.title + var description by Tasks.description + var isCompleted by Tasks.isCompleted + + override fun toString(): String { + return "Task(id=$id, title=$title, completed=$isCompleted)" + } +} diff --git a/documentation-website/Writerside/snippets/get-started-with-exposed/.gitattributes b/documentation-website/Writerside/snippets/get-started-with-exposed/.gitattributes deleted file mode 100644 index 097f9f98d9..0000000000 --- a/documentation-website/Writerside/snippets/get-started-with-exposed/.gitattributes +++ /dev/null @@ -1,9 +0,0 @@ -# -# https://help.github.com/articles/dealing-with-line-endings/ -# -# Linux start script should use lf -/gradlew text eol=lf - -# These are Windows script files and should use crlf -*.bat text eol=crlf - diff --git a/documentation-website/Writerside/snippets/get-started-with-exposed/README.md b/documentation-website/Writerside/snippets/get-started-with-exposed/README.md index 0f68799cd9..0a7bfb1397 100644 --- a/documentation-website/Writerside/snippets/get-started-with-exposed/README.md +++ b/documentation-website/Writerside/snippets/get-started-with-exposed/README.md @@ -1,12 +1,20 @@ # Get started with Exposed tutorial project A sample Gradle/Kotlin project built by following the steps explained in -the [Get started with Exposed](https://jetbrains.github.io/Exposed/getting-started-with-exposed.html) tutorial. +the [Get started with Exposed](https://www.jetbrains.com/help/exposed/get-started-with-exposed.html) tutorial. + +## Build + +To build the application, navigate to the `snippets` folder and run the following command: + +```shell +./gradlew :get-started-with-exposed:build +``` ## Run To run the application, execute the following command in the repository's root directory: ```bash -./gradlew run +./gradlew :get-started-with-exposed:run ``` diff --git a/documentation-website/Writerside/snippets/get-started-with-exposed/app/build.gradle.kts b/documentation-website/Writerside/snippets/get-started-with-exposed/build.gradle.kts similarity index 96% rename from documentation-website/Writerside/snippets/get-started-with-exposed/app/build.gradle.kts rename to documentation-website/Writerside/snippets/get-started-with-exposed/build.gradle.kts index 3e512dee6f..126616bef9 100644 --- a/documentation-website/Writerside/snippets/get-started-with-exposed/app/build.gradle.kts +++ b/documentation-website/Writerside/snippets/get-started-with-exposed/build.gradle.kts @@ -31,7 +31,7 @@ dependencies { implementation(libs.guava) implementation(libs.exposed.core) implementation(libs.exposed.jdbc) - implementation("com.h2database:h2:2.2.224") + implementation(libs.h2) } // Apply a specific Java toolchain to ease working on different environments. diff --git a/documentation-website/Writerside/snippets/get-started-with-exposed/gradle/libs.versions.toml b/documentation-website/Writerside/snippets/get-started-with-exposed/gradle/libs.versions.toml deleted file mode 100644 index ce5bde2b44..0000000000 --- a/documentation-website/Writerside/snippets/get-started-with-exposed/gradle/libs.versions.toml +++ /dev/null @@ -1,16 +0,0 @@ -# This file was generated by the Gradle 'init' task. -# https://docs.gradle.org/current/userguide/platforms.html#sub::toml-dependencies-format - -[versions] -guava = "33.0.0-jre" -junit-jupiter-engine = "5.10.2" -exposed = "1.0.0-beta-4" - -[libraries] -guava = { module = "com.google.guava:guava", version.ref = "guava" } -junit-jupiter-engine = { module = "org.junit.jupiter:junit-jupiter-engine", version.ref = "junit-jupiter-engine" } -exposed-core = { module= "org.jetbrains.exposed:exposed-core", version.ref = "exposed"} -exposed-jdbc = { module= "org.jetbrains.exposed:exposed-jdbc", version.ref = "exposed"} - -[plugins] -jvm = { id = "org.jetbrains.kotlin.jvm", version = "2.0.0" } diff --git a/documentation-website/Writerside/snippets/get-started-with-exposed/gradle/wrapper/gradle-wrapper.jar b/documentation-website/Writerside/snippets/get-started-with-exposed/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index e6441136f3..0000000000 Binary files a/documentation-website/Writerside/snippets/get-started-with-exposed/gradle/wrapper/gradle-wrapper.jar and /dev/null differ diff --git a/documentation-website/Writerside/snippets/get-started-with-exposed/gradle/wrapper/gradle-wrapper.properties b/documentation-website/Writerside/snippets/get-started-with-exposed/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index a4413138c9..0000000000 --- a/documentation-website/Writerside/snippets/get-started-with-exposed/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,7 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip -networkTimeout=10000 -validateDistributionUrl=true -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists diff --git a/documentation-website/Writerside/snippets/get-started-with-exposed/gradlew b/documentation-website/Writerside/snippets/get-started-with-exposed/gradlew deleted file mode 100755 index b740cf1339..0000000000 --- a/documentation-website/Writerside/snippets/get-started-with-exposed/gradlew +++ /dev/null @@ -1,249 +0,0 @@ -#!/bin/sh - -# -# Copyright © 2015-2021 the original authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -############################################################################## -# -# Gradle start up script for POSIX generated by Gradle. -# -# Important for running: -# -# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is -# noncompliant, but you have some other compliant shell such as ksh or -# bash, then to run this script, type that shell name before the whole -# command line, like: -# -# ksh Gradle -# -# Busybox and similar reduced shells will NOT work, because this script -# requires all of these POSIX shell features: -# * functions; -# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», -# «${var#prefix}», «${var%suffix}», and «$( cmd )»; -# * compound commands having a testable exit status, especially «case»; -# * various built-in commands including «command», «set», and «ulimit». -# -# Important for patching: -# -# (2) This script targets any POSIX shell, so it avoids extensions provided -# by Bash, Ksh, etc; in particular arrays are avoided. -# -# The "traditional" practice of packing multiple parameters into a -# space-separated string is a well documented source of bugs and security -# problems, so this is (mostly) avoided, by progressively accumulating -# options in "$@", and eventually passing that to Java. -# -# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, -# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; -# see the in-line comments for details. -# -# There are tweaks for specific operating systems such as AIX, CygWin, -# Darwin, MinGW, and NonStop. -# -# (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt -# within the Gradle project. -# -# You can find Gradle at https://github.com/gradle/gradle/. -# -############################################################################## - -# Attempt to set APP_HOME - -# Resolve links: $0 may be a link -app_path=$0 - -# Need this for daisy-chained symlinks. -while - APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path - [ -h "$app_path" ] -do - ls=$( ls -ld "$app_path" ) - link=${ls#*' -> '} - case $link in #( - /*) app_path=$link ;; #( - *) app_path=$APP_HOME$link ;; - esac -done - -# This is normally unused -# shellcheck disable=SC2034 -APP_BASE_NAME=${0##*/} -# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD=maximum - -warn () { - echo "$*" -} >&2 - -die () { - echo - echo "$*" - echo - exit 1 -} >&2 - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "$( uname )" in #( - CYGWIN* ) cygwin=true ;; #( - Darwin* ) darwin=true ;; #( - MSYS* | MINGW* ) msys=true ;; #( - NONSTOP* ) nonstop=true ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD=$JAVA_HOME/jre/sh/java - else - JAVACMD=$JAVA_HOME/bin/java - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD=java - if ! command -v java >/dev/null 2>&1 - then - die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -fi - -# Increase the maximum file descriptors if we can. -if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then - case $MAX_FD in #( - max*) - # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC2039,SC3045 - MAX_FD=$( ulimit -H -n ) || - warn "Could not query maximum file descriptor limit" - esac - case $MAX_FD in #( - '' | soft) :;; #( - *) - # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC2039,SC3045 - ulimit -n "$MAX_FD" || - warn "Could not set maximum file descriptor limit to $MAX_FD" - esac -fi - -# Collect all arguments for the java command, stacking in reverse order: -# * args from the command line -# * the main class name -# * -classpath -# * -D...appname settings -# * --module-path (only if needed) -# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. - -# For Cygwin or MSYS, switch paths to Windows format before running java -if "$cygwin" || "$msys" ; then - APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) - - JAVACMD=$( cygpath --unix "$JAVACMD" ) - - # Now convert the arguments - kludge to limit ourselves to /bin/sh - for arg do - if - case $arg in #( - -*) false ;; # don't mess with options #( - /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath - [ -e "$t" ] ;; #( - *) false ;; - esac - then - arg=$( cygpath --path --ignore --mixed "$arg" ) - fi - # Roll the args list around exactly as many times as the number of - # args, so each arg winds up back in the position where it started, but - # possibly modified. - # - # NB: a `for` loop captures its iteration list before it begins, so - # changing the positional parameters here affects neither the number of - # iterations, nor the values presented in `arg`. - shift # remove old arg - set -- "$@" "$arg" # push replacement arg - done -fi - - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - -# Collect all arguments for the java command: -# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, -# and any embedded shellness will be escaped. -# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be -# treated as '${Hostname}' itself on the command line. - -set -- \ - "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ - "$@" - -# Stop when "xargs" is not available. -if ! command -v xargs >/dev/null 2>&1 -then - die "xargs is not available" -fi - -# Use "xargs" to parse quoted args. -# -# With -n1 it outputs one arg per line, with the quotes and backslashes removed. -# -# In Bash we could simply go: -# -# readarray ARGS < <( xargs -n1 <<<"$var" ) && -# set -- "${ARGS[@]}" "$@" -# -# but POSIX shell has neither arrays nor command substitution, so instead we -# post-process each arg (as a line of input to sed) to backslash-escape any -# character that might be a shell metacharacter, then use eval to reverse -# that process (while maintaining the separation between arguments), and wrap -# the whole thing up as a single "set" statement. -# -# This will of course break if any of these variables contains a newline or -# an unmatched quote. -# - -eval "set -- $( - printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | - xargs -n1 | - sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | - tr '\n' ' ' - )" '"$@"' - -exec "$JAVACMD" "$@" diff --git a/documentation-website/Writerside/snippets/get-started-with-exposed/gradlew.bat b/documentation-website/Writerside/snippets/get-started-with-exposed/gradlew.bat deleted file mode 100644 index 25da30dbde..0000000000 --- a/documentation-website/Writerside/snippets/get-started-with-exposed/gradlew.bat +++ /dev/null @@ -1,92 +0,0 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%"=="" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%"=="" set DIRNAME=. -@rem This is normally unused -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if %ERRORLEVEL% equ 0 goto execute - -echo. 1>&2 -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. 1>&2 -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/documentation-website/Writerside/snippets/get-started-with-exposed/settings.gradle.kts b/documentation-website/Writerside/snippets/get-started-with-exposed/settings.gradle.kts deleted file mode 100644 index 8dcc9f58a0..0000000000 --- a/documentation-website/Writerside/snippets/get-started-with-exposed/settings.gradle.kts +++ /dev/null @@ -1,14 +0,0 @@ -/* - * This file was generated by the Gradle 'init' task. - * - * The settings file is used to specify which projects to include in your build. - * For more detailed information on multi-project builds, please refer to https://docs.gradle.org/8.8/userguide/multi_project_builds.html in the Gradle documentation. - */ - -plugins { - // Apply the foojay-resolver plugin to allow automatic download of JDKs - id("org.gradle.toolchains.foojay-resolver-convention") version "0.9.0" -} - -rootProject.name = "exposed-kotlin-app" -include("app") diff --git a/documentation-website/Writerside/snippets/get-started-with-exposed/app/src/main/kotlin/org/example/App.kt b/documentation-website/Writerside/snippets/get-started-with-exposed/src/main/kotlin/org/example/App.kt similarity index 97% rename from documentation-website/Writerside/snippets/get-started-with-exposed/app/src/main/kotlin/org/example/App.kt rename to documentation-website/Writerside/snippets/get-started-with-exposed/src/main/kotlin/org/example/App.kt index 8af223d01d..26c225b39c 100644 --- a/documentation-website/Writerside/snippets/get-started-with-exposed/app/src/main/kotlin/org/example/App.kt +++ b/documentation-website/Writerside/snippets/get-started-with-exposed/src/main/kotlin/org/example/App.kt @@ -8,7 +8,6 @@ import org.jetbrains.exposed.v1.core.* import org.jetbrains.exposed.v1.core.SqlExpressionBuilder.eq import org.jetbrains.exposed.v1.jdbc.Database import org.jetbrains.exposed.v1.jdbc.SchemaUtils -import org.jetbrains.exposed.v1.jdbc.addLogger import org.jetbrains.exposed.v1.jdbc.deleteWhere import org.jetbrains.exposed.v1.jdbc.insert import org.jetbrains.exposed.v1.jdbc.select diff --git a/documentation-website/Writerside/snippets/get-started-with-exposed/app/src/main/kotlin/org/example/Task.kt b/documentation-website/Writerside/snippets/get-started-with-exposed/src/main/kotlin/org/example/Task.kt similarity index 100% rename from documentation-website/Writerside/snippets/get-started-with-exposed/app/src/main/kotlin/org/example/Task.kt rename to documentation-website/Writerside/snippets/get-started-with-exposed/src/main/kotlin/org/example/Task.kt diff --git a/documentation-website/Writerside/snippets/settings.gradle.kts b/documentation-website/Writerside/snippets/settings.gradle.kts index 095b2889a7..875f9f9ee7 100644 --- a/documentation-website/Writerside/snippets/settings.gradle.kts +++ b/documentation-website/Writerside/snippets/settings.gradle.kts @@ -23,3 +23,5 @@ include("exposed-modules-groovy-gradle") include("exposed-sql-functions") include("exposed-transactions") include("exposed-migrations") +include("get-started-with-exposed") +include("get-started-with-exposed-dao") diff --git a/documentation-website/Writerside/topics/About.topic b/documentation-website/Writerside/topics/About.topic index c0d35ad8a5..138402a09a 100644 --- a/documentation-website/Writerside/topics/About.topic +++ b/documentation-website/Writerside/topics/About.topic @@ -63,7 +63,7 @@ - + diff --git a/documentation-website/Writerside/topics/Getting-Started-with-Exposed.topic b/documentation-website/Writerside/topics/Get-Started-with-Exposed.topic similarity index 89% rename from documentation-website/Writerside/topics/Getting-Started-with-Exposed.topic rename to documentation-website/Writerside/topics/Get-Started-with-Exposed.topic index c2756423e0..db2841b8ee 100644 --- a/documentation-website/Writerside/topics/Getting-Started-with-Exposed.topic +++ b/documentation-website/Writerside/topics/Get-Started-with-Exposed.topic @@ -2,8 +2,9 @@ + id="Get-Started-with-Exposed" title="Get started with Exposed, an ORM framework for Kotlin"> + @@ -67,8 +68,8 @@ the following commands to create a new folder and change directory into it:

- mkdir exposed-kotlin-app - cd exposed-kotlin-app + mkdir %project_name% + cd %project_name% @@ -136,24 +137,26 @@

- Before you start using Exposed, you need to provide dependencies to your project. + Before you start using Exposed, you need to add dependencies to your project.

Navigate to the gradle/libs.versions.toml - file and define the Exposed version and libraries: + file and define the Exposed and H2 version and artifacts:

[versions] //... exposed = "%exposed_version%" + h2 = "%h2_db_version%" [libraries] //... exposed-core = { module = "org.jetbrains.exposed:exposed-core", version.ref = "exposed" } exposed-jdbc = { module = "org.jetbrains.exposed:exposed-jdbc", version.ref = "exposed" } + h2 = { module = "com.h2database:h2", version.ref = "h2" }
  • @@ -177,7 +180,7 @@ //... implementation(libs.exposed.core) implementation(libs.exposed.jdbc) - implementation("com.h2database:h2:%h2_db_version%") + implementation(libs.h2) //... } @@ -189,7 +192,7 @@

    - Every database access using Exposed is started by obtaining a connection and creating a transaction. + Whenever you access a database using Exposed, you start by obtaining a connection and creating a transaction. To configure the database connection, use the Database.connect() function.

    @@ -213,8 +216,8 @@ file with the following implementation:

    The Database.connect() function creates an instance of a class that represents @@ -249,21 +252,20 @@ to the database will be established later when a database operation is performed. - By default, Exposed uses a ServiceLoader to get an implementation of the DatabaseConnectionAutoRegistration - interface that represents a connection accessed by the Database instance. - This can be modified when calling the Database.connect method by providing an argument to connectionAutoRegistration - in the parameter list. + By default, Exposed automatically registers the database connection. You can change + this behavior by setting the connectionAutoRegistration parameter + when calling Database.connect(). -

    - With this, you've added Exposed to your Kotlin project and configured a database connection. - You're now ready to define your data model and engage with the database using Exposed's DSL API. -

    +

    + With this, you've added Exposed to your Kotlin project and configured a database connection. + You're now ready to define your data model and engage with the database using Exposed's DSL. +

    - In Exposed, a database table is represented by an object inherited from the Table class. + In Exposed, a database table is represented by an object inherited from the Table class. To define the table object, follow the steps below.

    @@ -281,14 +283,14 @@

    Open Task.kt and add the following table definition:

    In the Table constructor, passing the name tasks configures a custom name for the table. Keep in mind that if no custom name is specified, Exposed will generate one from the class name, which might lead to unexpected results.

    -

    Within the Tasks object, four columns are defined:

    +

    Within the Tasks object, the following columns are defined:

  • id of type Int is defined with the integer() method. @@ -318,9 +320,10 @@

    With Exposed’s DSL API, you can interact with a database using a type-safe syntax similar to SQL. - Before you start executing database operations, you must open a transaction. + Before you start executing database operations, you must open a + transaction.

    -

    +

    A transaction is represented by an instance of the Transaction class, within which you can define and manipulate data using its lambda function. Exposed will automatically manage the opening and closing of the transaction in the background, ensuring seamless operation. @@ -333,8 +336,8 @@ file and add the following transaction function:

    Let's break down the code and go over each section.

    @@ -346,8 +349,8 @@ Once the table has been created, you use the Table extension method insert() to add two new Task records.

    Within the insert block, you set the values for @@ -369,8 +372,8 @@ of rows and to retrieve the isCompleted value for each row in the table.

    Using groupBy() groups the results of the query by the isCompleted @@ -397,8 +400,8 @@ At the beginning of your transaction block, add the following line to enable SQL query logging:

    @@ -426,8 +429,8 @@

    In the same transaction() function, add the following code to your implementation:

    Here's the breakdown:

    @@ -436,8 +439,8 @@ the isCompleted field of the found task is set to true.

    Unlike the insert() function, update() returns the number of updated rows. @@ -446,8 +449,8 @@ equal to taskId.

    Using the single() extension function @@ -457,8 +460,8 @@ The deleteWhere() function, on the other hand, deletes the task with the specified condition.

    Similarly to update(), it returns the number of rows that have been deleted. @@ -487,7 +490,7 @@ - + It might be useful to know that if a second transaction is opened after the first one, you will find that the table and its data has been lost even though the app hasn't stopped. This is diff --git a/documentation-website/Writerside/topics/Get-started-with-Exposed-DAO.md b/documentation-website/Writerside/topics/Get-started-with-Exposed-DAO.md new file mode 100644 index 0000000000..07a335bf25 --- /dev/null +++ b/documentation-website/Writerside/topics/Get-started-with-Exposed-DAO.md @@ -0,0 +1,280 @@ +# Get started with Exposed's DAO API + + + + + + + + + In this tutorial, you’ll learn how to create and query a table in Kotlin with Exposed's DAO API. + + + Learn how to create and query tables in Kotlin with Exposed's DAO API. + + +In this tutorial, you’ll learn how to use Exposed’s Data Access Object (DAO) API to store and retrieve data in a +relational database by building a simple console application. + +By the end of this tutorial, you’ll be able to do the following: + +- Configure a database connection using an in-memory database. +- Define database tables and corresponding DAO entities. +- Perform basic CRUD (Create, Read, Update, and Delete) operations using object-oriented style. + + + + + +## Add dependencies + + + +Before you start using Exposed, you need to add dependencies to your project. + + +Navigate to the **gradle/libs.versions.toml** file and define the Exposed and H2 versions and artifacts: + +```kotlin +[versions] +//... +exposed = "%exposed_version%" +h2 = "%h2_db_version%" + +[libraries] +//... +exposed-core = { module = "org.jetbrains.exposed:exposed-core", version.ref = "exposed" } +exposed-dao = { module = "org.jetbrains.exposed:exposed-dao", version.ref = "exposed" } +exposed-jdbc = { module = "org.jetbrains.exposed:exposed-jdbc", version.ref = "exposed" } +h2 = { module = "com.h2database:h2", version.ref = "h2" } +``` + +- The `exposed-core` module provides the foundational components and abstractions needed to work with databases in a +type-safe manner and includes the DSL API. +- The `exposed-dao` module allows you to work with the Data Access Object (DAO) API. +- The `exposed-jdbc` module is an extension of the exposed-core module that adds support for Java +Database Connectivity (JDBC). + + + + +Navigate to the **app/build.gradle.kts** file and add the Exposed and H2 database modules into the `dependencies` block: + +```kotlin +dependencies { + //... + implementation(libs.exposed.core) + implementation(libs.exposed.dao) + implementation(libs.exposed.jdbc) + implementation(libs.h2) + //... +} +``` + + + + + + +## Configure a database connection + +Whenever you access a database using Exposed, you start by obtaining a connection and creating a transaction. +To configure the database connection, use the `Database.connect()` function. + + + +With this, you've added Exposed to your Kotlin project and configured a database connection. +You're now ready to define your data model and engage with the database using Exposed's DAO API. + +## Define a table object + +Exposed's DAO API provides the base `IdTable` class and its subclasses to define tables that use a standard `id` column +as the primary key. +To define the table object, follow the steps below. + + + + +In the **app/src/main/kotlin/org/example/** folder, create a new **Task.kt** file. + + + + +Open **Task.kt** and add the following table definition: + +```kotlin +``` +{src="get-started-with-exposed-dao/src/main/kotlin/org/example/Task.kt" include-lines="1-2,5,8,10-14"} + +In the `IntIdTable` constructor, passing the name `tasks` configures a custom +name for the table. If you don't provide a name, Exposed will derive it from the object name, which may lead to +unexpected results depending on naming conventions. + +The `Tasks` object defines the following columns: + +- `title` and `description` are `String` columns, created using the `varchar()` function. Each column has a maximum +length of 128 characters. +- `isCompleted` is a `Boolean` column, defined using the `bool()` function. Using the `default(false)` call, you +configure the default value to `false`. + +The `IntIdTable` class automatically adds an auto-incrementing integer `id` +column as the primary key for the table. At this point, you have defined a table with columns, which essentially +creates the blueprint for the `tasks` table. + + + + +## Define an entity + +When using the DAO approach, each table defined using `IntIdTable` must be associated with a corresponding +[entity class](DAO-Entity-definition.topic). +The entity class represents individual records in the table and is uniquely identified by a primary key. + +To define the entity, update your **Task.kt** file with the following code: + +```kotlin +``` +{src="get-started-with-exposed-dao/src/main/kotlin/org/example/Task.kt" include-lines="3-4,6-8,15-28"} + +- `Task` extends `IntEntity`, which is a base class for entities with an `Int`-based primary key. +- The `EntityID` parameter represents the primary key of the database row this entity maps to. +- The `companion object` extends `IntEntityClass`, linking the entity class to the `Tasks` table. +- Each property (`title`, `description`, and `isCompleted`) is delegated to its corresponding column in the `Tasks` +table using Kotlin's `by` keyword. +- The `toString()` function customizes how a `Task` instance is represented as a string. This is especially +useful for debugging or logging. When printed, the output will include the entity’s ID, title, and completion status. + +## Create and query a table + +With Exposed’s DAO API, you can interact with your database using a type-safe, object-oriented syntax similar to +working with regular Kotlin classes. When executing any database operations, you must run them inside a +transaction. + + + +Open your **App.kt** file and add the following transaction function: + +```kotlin +``` +{src="get-started-with-exposed-dao/src/main/kotlin/org/example/App.kt" include-lines="1-2,4-11,16-33,42-43"} + +First, you create the tasks table using the `SchemaUtils.create()` method. The `SchemaUtils` object holds utility +methods for creating, altering, and dropping database objects. + +Once the table has been created, you use the `IntEntityClass` extension method `.new()` to add two new `Task` records: + +```kotlin +``` +{src="get-started-with-exposed-dao/src/main/kotlin/org/example/App.kt" include-symbol="task1,task2"} + +In this example, `task1` and `task2` are instances of the `Task` entity, each representing a new row in the `Tasks` +table. Within the `new` block, you set the values for each column. Exposed will translate the functions into the +following SQL queries: + +```sql +INSERT INTO TASKS ("name", DESCRIPTION, COMPLETED) VALUES ('Learn Exposed DAO', 'Follow the DAO tutorial', FALSE) +INSERT INTO TASKS ("name", DESCRIPTION, COMPLETED) VALUES ('Read The Hobbit', 'Read chapter one', TRUE) +``` + +With the `.find()` method you then perform a filtered query, retrieving all tasks where `isCompleted` is `true`: + +```kotlin +``` +{src="get-started-with-exposed-dao/src/main/kotlin/org/example/App.kt" include-symbol="completed"} + +Before you test the code, it would be handy to be able to inspect the SQL statements and queries Exposed sends to the +database. For this, you need to add a logger. + +## Enable logging + +At the beginning of your `transaction` block, add the following to enable SQL query logging: + +```kotlin +``` +{src="get-started-with-exposed-dao/src/main/kotlin/org/example/App.kt" include-lines="3,7-8,11-14,42-43"} + +## Run the application + + + +The application will start in the **Run** tool window at the bottom of the IDE. There you will be able to see the SQL +logs along with the printed results: + +```generic +SQL: SELECT SETTING_VALUE FROM INFORMATION_SCHEMA.SETTINGS WHERE SETTING_NAME = 'MODE' +SQL: CREATE TABLE IF NOT EXISTS TASKS (ID INT AUTO_INCREMENT PRIMARY KEY, "name" VARCHAR(128) NOT NULL, DESCRIPTION VARCHAR(128) NOT NULL, COMPLETED BOOLEAN DEFAULT FALSE NOT NULL) +SQL: INSERT INTO TASKS ("name", DESCRIPTION, COMPLETED) VALUES ('Learn Exposed DAO', 'Follow the DAO tutorial', FALSE) +SQL: INSERT INTO TASKS ("name", DESCRIPTION, COMPLETED) VALUES ('Read The Hobbit', 'Read chapter one', TRUE) +Created new tasks with ids 1 and 2 +SQL: SELECT TASKS.ID, TASKS."name", TASKS.DESCRIPTION, TASKS.COMPLETED FROM TASKS WHERE TASKS.COMPLETED = TRUE +Completed tasks: 1 +``` + +## Update and delete a task + +Let’s extend the app’s functionality by updating and deleting a task. + + + + +In the same `transaction()` function, add the following code to your implementation: + +```kotlin +``` +{src="get-started-with-exposed-dao/src/main/kotlin/org/example/App.kt" include-lines="11,13-15,34-42"} + +You update the value of a property just as you would with any property in a Kotlin class: + +```kotlin +``` +{src="get-started-with-exposed-dao/src/main/kotlin/org/example/App.kt" include-lines="35-36"} + +Similarly, to delete a task, you use the `.delete()` method on the entity: + +```kotlin +``` +{src="get-started-with-exposed-dao/src/main/kotlin/org/example/App.kt" include-lines="40"} + + + + + +You should now see the following result: + +```generic +SQL: SELECT SETTING_VALUE FROM INFORMATION_SCHEMA.SETTINGS WHERE SETTING_NAME = 'MODE' +SQL: CREATE TABLE IF NOT EXISTS TASKS (ID INT AUTO_INCREMENT PRIMARY KEY, "name" VARCHAR(128) NOT NULL, DESCRIPTION VARCHAR(128) NOT NULL, COMPLETED BOOLEAN DEFAULT FALSE NOT NULL) +SQL: INSERT INTO TASKS ("name", DESCRIPTION, COMPLETED) VALUES ('Learn Exposed DAO', 'Follow the DAO tutorial', FALSE) +SQL: INSERT INTO TASKS ("name", DESCRIPTION, COMPLETED) VALUES ('Read The Hobbit', 'Read chapter one', TRUE) +Created new tasks with ids 1 and 2 +SQL: SELECT TASKS.ID, TASKS."name", TASKS.DESCRIPTION, TASKS.COMPLETED FROM TASKS WHERE TASKS.COMPLETED = TRUE +Completed tasks: 1 +Updated task1: Task(id=1, title=Try Exposed DAO, completed=true) +SQL: UPDATE TASKS SET COMPLETED=TRUE, "name"='Try Exposed DAO' WHERE ID = 1 +SQL: DELETE FROM TASKS WHERE TASKS.ID = 2 +SQL: SELECT TASKS.ID, TASKS."name", TASKS.DESCRIPTION, TASKS.COMPLETED FROM TASKS +Remaining tasks: [Task(id=1, title=Try Exposed DAO, completed=true)] +``` + +> Exposed does not immediately issue an `UPDATE` statement when you modify entity properties such as +> `task1.title` or `task1.isCompleted`. Instead, it caches those changes in memory and flushes them to the database right +> before the next read operation or at the end of the transaction: +> +> ```generic +> SQL: UPDATE TASKS SET COMPLETED=TRUE, "name"='Try Exposed DAO' WHERE ID = 1 +> ``` +> +{style="note"} + + + + + +## Next steps + +Great job! You've built a simple console application using Exposed's DAO API to create, query, and manipulate task +data in an in-memory database. + +Now that you've covered the fundamentals, you're ready to dive deeper into what the DAO API offers. Continue exploring +[CRUD operations](DAO-CRUD-Operations.topic) or learn how to [define relationships between entities](DAO-Relationships.topic). +These next chapters will help you build more complex, real-world data models using Exposed’s type-safe, object-oriented approach. diff --git a/documentation-website/Writerside/topics/Home.topic b/documentation-website/Writerside/topics/Home.topic index 2b1332a975..0dcae23684 100644 --- a/documentation-website/Writerside/topics/Home.topic +++ b/documentation-website/Writerside/topics/Home.topic @@ -14,7 +14,7 @@ - Get Started with Exposed