diff --git a/documentation-website/Writerside/hi.tree b/documentation-website/Writerside/hi.tree index 08b730e0c6..9f81c928e7 100644 --- a/documentation-website/Writerside/hi.tree +++ b/documentation-website/Writerside/hi.tree @@ -7,7 +7,7 @@ start-page="Home.topic"> - + diff --git a/documentation-website/Writerside/images/intellij_idea_gradle_icon.svg b/documentation-website/Writerside/images/intellij_idea_gradle_icon.svg new file mode 100644 index 0000000000..3256098754 --- /dev/null +++ b/documentation-website/Writerside/images/intellij_idea_gradle_icon.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/documentation-website/Writerside/images/intellij_idea_gradle_icon_dark.svg b/documentation-website/Writerside/images/intellij_idea_gradle_icon_dark.svg new file mode 100644 index 0000000000..042609f889 --- /dev/null +++ b/documentation-website/Writerside/images/intellij_idea_gradle_icon_dark.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/documentation-website/Writerside/images/intellij_idea_gutter_icon.svg b/documentation-website/Writerside/images/intellij_idea_gutter_icon.svg new file mode 100644 index 0000000000..0e2fbae820 --- /dev/null +++ b/documentation-website/Writerside/images/intellij_idea_gutter_icon.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/documentation-website/Writerside/images/intellij_idea_gutter_icon_dark.svg b/documentation-website/Writerside/images/intellij_idea_gutter_icon_dark.svg new file mode 100644 index 0000000000..b1321a7c38 --- /dev/null +++ b/documentation-website/Writerside/images/intellij_idea_gutter_icon_dark.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/documentation-website/Writerside/images/intellij_idea_rerun_icon.svg b/documentation-website/Writerside/images/intellij_idea_rerun_icon.svg new file mode 100644 index 0000000000..f66409894a --- /dev/null +++ b/documentation-website/Writerside/images/intellij_idea_rerun_icon.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/documentation-website/Writerside/images/intellij_idea_rerun_icon_dark.svg b/documentation-website/Writerside/images/intellij_idea_rerun_icon_dark.svg new file mode 100644 index 0000000000..cf28e741f6 --- /dev/null +++ b/documentation-website/Writerside/images/intellij_idea_rerun_icon_dark.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/documentation-website/Writerside/snippets/get-started-with-exposed/.gitattributes b/documentation-website/Writerside/snippets/get-started-with-exposed/.gitattributes new file mode 100644 index 0000000000..097f9f98d9 --- /dev/null +++ b/documentation-website/Writerside/snippets/get-started-with-exposed/.gitattributes @@ -0,0 +1,9 @@ +# +# 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 new file mode 100644 index 0000000000..0f68799cd9 --- /dev/null +++ b/documentation-website/Writerside/snippets/get-started-with-exposed/README.md @@ -0,0 +1,12 @@ +# 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. + +## Run + +To run the application, execute the following command in the repository's root directory: + +```bash +./gradlew 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/app/build.gradle.kts new file mode 100644 index 0000000000..3e512dee6f --- /dev/null +++ b/documentation-website/Writerside/snippets/get-started-with-exposed/app/build.gradle.kts @@ -0,0 +1,52 @@ +/* + * 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.jdbc) + implementation("com.h2database:h2:2.2.224") +} + +// 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/app/src/main/kotlin/org/example/App.kt b/documentation-website/Writerside/snippets/get-started-with-exposed/app/src/main/kotlin/org/example/App.kt new file mode 100644 index 0000000000..13ea6a974c --- /dev/null +++ b/documentation-website/Writerside/snippets/get-started-with-exposed/app/src/main/kotlin/org/example/App.kt @@ -0,0 +1,53 @@ +/* + * This source file was generated by the Gradle 'init' task + */ +package org.example + +import Tasks +import org.jetbrains.exposed.sql.* +import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq +import org.jetbrains.exposed.sql.transactions.transaction + +fun main() { + Database.connect("jdbc:h2:mem:test", driver = "org.h2.Driver") + + transaction { + // print sql to std-out + addLogger(StdOutSqlLogger) + + // ... + + SchemaUtils.create(Tasks) + + val taskId = Tasks.insert { + it[title] = "Learn Exposed" + it[description] = "Go through the Get started with Exposed tutorial" + } get Tasks.id + + val secondTaskId = Tasks.insert { + it[title] = "Read The Hobbit" + it[description] = "Read the first two chapters of The Hobbit" + it[isCompleted] = true + } get Tasks.id + + println("Created new tasks with ids $taskId and $secondTaskId.") + + Tasks.select(Tasks.id.count(), Tasks.isCompleted).groupBy(Tasks.isCompleted).forEach { + println("${it[Tasks.isCompleted]}: ${it[Tasks.id.count()]} ") + } + + // Update a task + Tasks.update({ Tasks.id eq taskId }) { + it[isCompleted] = true + } + + val updatedTask = Tasks.select(Tasks.isCompleted).where(Tasks.id eq taskId).single() + + println("Updated task details: $updatedTask") + + // Delete a task + Tasks.deleteWhere { id eq secondTaskId } + + println("Remaining tasks: ${Tasks.selectAll().toList()}") + } +} 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/app/src/main/kotlin/org/example/Task.kt new file mode 100644 index 0000000000..946a1ce666 --- /dev/null +++ b/documentation-website/Writerside/snippets/get-started-with-exposed/app/src/main/kotlin/org/example/Task.kt @@ -0,0 +1,10 @@ +import org.jetbrains.exposed.sql.Table + +const val MAX_VARCHAR_LENGTH = 128 + +object Tasks : Table("tasks") { + val id = integer("id").autoIncrement() + val title = varchar("name", MAX_VARCHAR_LENGTH) + val description = varchar("description", MAX_VARCHAR_LENGTH) + val isCompleted = bool("completed").default(false) +} 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 new file mode 100644 index 0000000000..d8c0b3a831 --- /dev/null +++ b/documentation-website/Writerside/snippets/get-started-with-exposed/gradle/libs.versions.toml @@ -0,0 +1,16 @@ +# 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 = "0.51.1" + +[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 = "1.9.22" } 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 new file mode 100644 index 0000000000..e6441136f3 Binary files /dev/null and b/documentation-website/Writerside/snippets/get-started-with-exposed/gradle/wrapper/gradle-wrapper.jar 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 new file mode 100644 index 0000000000..a4413138c9 --- /dev/null +++ b/documentation-website/Writerside/snippets/get-started-with-exposed/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +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 new file mode 100755 index 0000000000..b740cf1339 --- /dev/null +++ b/documentation-website/Writerside/snippets/get-started-with-exposed/gradlew @@ -0,0 +1,249 @@ +#!/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 new file mode 100644 index 0000000000..25da30dbde --- /dev/null +++ b/documentation-website/Writerside/snippets/get-started-with-exposed/gradlew.bat @@ -0,0 +1,92 @@ +@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 new file mode 100644 index 0000000000..6bec306515 --- /dev/null +++ b/documentation-website/Writerside/snippets/get-started-with-exposed/settings.gradle.kts @@ -0,0 +1,14 @@ +/* + * 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.8.0" +} + +rootProject.name = "exposed-kotlin-app" +include("app") diff --git a/documentation-website/Writerside/snippets/init-kotlin-gradle-app.zip b/documentation-website/Writerside/snippets/init-kotlin-gradle-app.zip new file mode 100644 index 0000000000..9c51303c0d Binary files /dev/null and b/documentation-website/Writerside/snippets/init-kotlin-gradle-app.zip differ diff --git a/documentation-website/Writerside/topics/Getting-Started-with-Exposed.md b/documentation-website/Writerside/topics/Getting-Started-with-Exposed.md deleted file mode 100644 index 513d4ef3d0..0000000000 --- a/documentation-website/Writerside/topics/Getting-Started-with-Exposed.md +++ /dev/null @@ -1,168 +0,0 @@ -# Getting Started with Exposed - -## Adding Dependencies - -Before starting using Exposed, you need to add the dependencies to your project. - - - - -val exposed_version = "0.52.0" -dependencies { - implementation("org.jetbrains.exposed", "exposed-core", exposed_version) - implementation("org.jetbrains.exposed", "exposed-dao", exposed_version) - implementation("org.jetbrains.exposed", "exposed-jdbc", exposed_version) -} - - - - - - - org.jetbrains.exposed - exposed-core - 0.52.0 - - - org.jetbrains.exposed - exposed-dao - 0.52.0 - - - org.jetbrains.exposed - exposed-jdbc - 0.52.0 - - -]]> - - - - - -Other modules are available. Detailed information about them is located in the [Modules](Exposed-Modules.md) section. - - -## Getting Started - -### Starting a transaction - -Every database access using Exposed is started by obtaining a connection and creating a transaction. - -To get a connection: - -```kotlin -Database.connect("jdbc:h2:mem:test", driver = "org.h2.Driver") -``` - -It is also possible to provide `javax.sql.DataSource` for advanced behaviors such as connection pooling: - -```kotlin -Database.connect(dataSource) -``` - -More details on [Database and DataSource](Database-and-DataSource.md). - -After obtaining a connection, all SQL statements should be placed inside a transaction: - -```kotlin -transaction { - // Statements here -} -``` - -To see the actual DB calls, add a logger: - -```kotlin -transaction { - // print sql to std-out - addLogger(StdOutSqlLogger) -} -``` - -To log DB calls when using Exposed with a **Spring Boot** application, add the following property to the `application.properties` file: -```ini -spring.exposed.show-sql=true -``` - -The `exposed-spring-boot-starter` [README](https://github.com/JetBrains/Exposed/tree/main/exposed-spring-boot-starter#configuring-exposed) covers the necessary steps to configure Exposed to use this and any [other properties](https://github.com/JetBrains/Exposed/tree/main/exposed-spring-boot-starter#automatic-schema-creation). - -Alternatively, the `SpringTransactionManager` class has the parameter `showSql`, which can be set to `true` if a transaction manager bean is defined manually. - -### DSL & DAO - -Exposed comes in two flavors: DSL (Domain-Specific Language) and DAO (Data Access Object). -On a high level, DSL means type-safe syntax that is similar to SQL, whereas DAO means doing CRUD operations on entities. -Observe the below examples and head on to the specific section of each API for more details. - -### Your first Exposed DSL - -```kotlin - - -fun main(args: Array) { - //an example connection to H2 DB - Database.connect("jdbc:h2:mem:test", driver = "org.h2.Driver") - - transaction { - // print sql to std-out - addLogger(StdOutSqlLogger) - - SchemaUtils.create (Cities) - - // insert new city. SQL: INSERT INTO Cities (name) VALUES ('St. Petersburg') - val stPeteId = Cities.insert { - it[name] = "St. Petersburg" - } get Cities.id - - // 'select *' SQL: SELECT Cities.id, Cities.name FROM Cities - println("Cities: ${Cities.selectAll()}") - } -} - -object Cities: IntIdTable() { - val name = varchar("name", 50) -} - -``` - -More on [DSL API](Deep-Dive-into-DSL.md) - -### Your first Exposed DAO - -```kotlin - - -fun main(args: Array) { - //an example connection to H2 DB - Database.connect("jdbc:h2:mem:test", driver = "org.h2.Driver") - - transaction { - // print sql to std-out - addLogger(StdOutSqlLogger) - - SchemaUtils.create (Cities) - - // insert new city. SQL: INSERT INTO Cities (name) VALUES ('St. Petersburg') - val stPete = City.new { - name = "St. Petersburg" - } - - // 'select *' SQL: SELECT Cities.id, Cities.name FROM Cities - println("Cities: ${City.all()}") - } -} - -object Cities: IntIdTable() { - val name = varchar("name", 50) -} - -class City(id: EntityID) : IntEntity(id) { - companion object : IntEntityClass(Cities) - - var name by Cities.name -} -``` - -More on [DAO API](Deep-Dive-into-DAO.md) diff --git a/documentation-website/Writerside/topics/Getting-Started-with-Exposed.topic b/documentation-website/Writerside/topics/Getting-Started-with-Exposed.topic new file mode 100644 index 0000000000..c8cac88ed8 --- /dev/null +++ b/documentation-website/Writerside/topics/Getting-Started-with-Exposed.topic @@ -0,0 +1,508 @@ + + + + + + + + + In this tutorial, you’ll learn how to create and query a table in Kotlin with Exposed's DSL API. + + + Learn how to create and query tables in Kotlin with Exposed's DSL API. + +

+ In this tutorial, you’ll learn how to use Exposed’s Domain-Specific Language (DSL) 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 database connections using an in-memory database.
  • +
  • Define database tables using Exposed’s DSL.
  • +
  • Perform basic CRUD (Create, Read, Update, and Delete) operations on the database.
  • +
    + +

    + Before starting this tutorial, ensure that you have the following installed on your machine: +

    + +
  • + The latest + Gradle + distribution. +
  • +
  • A Java Development Kit (JDK), version 8 or higher.
  • +
  • An integrated development environment (IDE), such as + IntelliJ IDEA Ultimate + .

    + We recommend that you install + + IntelliJ IDEA Ultimate + + which comes with built-in + + database tools + + and the + + Exposed plugin + + for code completion and inspections. However, you can use another IDE of your choice. +

  • +
    + +
    + +

    + First, you will need a basic Kotlin project setup to build upon. You can + download a pre-initialized + project or follow the steps below to generate a new project with Gradle. +

    + + +

    In a terminal window, navigate to the destination where you want to create your project and run + the following commands to create a new folder and change directory into it: +

    + + mkdir exposed-kotlin-app + cd exposed-kotlin-app + +
    + +

    Run the gradle init task to initialize a new Gradle project:

    + + gradle init + +

    + When prompted, select the following options: +

    + +
  • 1: Application project type.
  • +
  • 2: Kotlin implementation language.
  • +
    +

    + For the other questions, press enter to use the default values. + The output will look like the following: +

    + + Select type of build to generate: + 1: Application + 2: Library + 3: Gradle plugin + 4: Basic (build structure only) + Enter selection (default: Application) [1..4] + Select implementation language: + 1: Java + 2: Kotlin + 3: Groovy + 4: Scala + 5: C++ + 6: Swift + Enter selection (default: Java) [1..6] 2 + Enter target Java version (min: 7, default: 21): + Project name (default: exposed-kotlin-app): + Select application structure: + 1: Single application project + 2: Application and library project + Enter selection (default: Single application project) [1..2] + Select build script DSL: + 1: Kotlin + 2: Groovy + Enter selection (default: Kotlin) [1..2] + Select test framework: + 1: kotlin.test + 2: JUnit Jupiter + Enter selection (default: kotlin.test) [1..2] + Generate build using new APIs and behavior (some features may change in the next minor release)? (default: no) [yes, no] + > Task :init + To learn more about Gradle by exploring our Samples at https://docs.gradle.org/8.8/samples/sample_building_kotlin_applications.html + BUILD SUCCESSFUL in 28s + 1 actionable task: 1 executed + +
    + +

    + Once the project has been initialized, open the project folder in your IDE. + To open the project in IntelliJ IDEA, use the following command: +

    + + idea . + +
    +
    +
    + +

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

    + + +

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

    + + [versions] + //... + exposed = "%exposed_version%" + + [libraries] + //... + exposed-core = { module = "org.jetbrains.exposed:exposed-core", version.ref = "exposed" } + exposed-jdbc = { module = "org.jetbrains.exposed:exposed-jdbc", version.ref = "exposed" } + + +
  • + 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-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: +

    + + dependencies { + //... + implementation(libs.exposed.core) + implementation(libs.exposed.jdbc) + implementation("com.h2database:h2:%h2_db_version%") + //... + } + +
    + + + +
    +
    + +

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

    + + +

    + Navigate to + app/src/main/kotlin/org/example/ + and open the + + App.kt + + file. +

    +
    + +

    + Replace the contents of the + + App.kt + + file with the following implementation: +

    + +

    + The Database.connect() function creates an instance of a class that represents + the database and takes two or more parameters. In this case, the connection URL and the driver. +

    + +
  • + jdbc:h2:mem:test is the database URL to connect to: + +
  • + jdbc specifies that this is a JDBC connection. +
  • +
  • + h2 indicates that the database is an H2 database. +
  • +
  • + mem specifies that the database is in-memory, meaning the data will only + exist in memory and will be lost when the application stops. +
  • +
  • + test is the name of the database. +
  • +
    + +
  • + org.h2.Driver specifies the H2 JDBC driver to be used for establishing the connection. +
  • + + + Note that invoking Database.connect() only configures the connection settings, + but it does not immediately establish a connection with the database. The actual connection + to the database will be established later when a database operation is performed. + +

    + 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. +

    +
    +
    +
    + +

    + In Exposed, a database table is represented by an object inherited from the Table class. + 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:

    + +

    + 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:

    + +
  • + id of type Int is defined with the integer() method. + The autoIncrement() function indicates that this column will be + an auto-incrementing integer, typically used for primary keys. +
  • +
  • + title and description of type String are defined + with the varchar() method. +
  • +
  • + isCompleted of type Boolean is defined with the + bool() method. Using the default() function, you configure the + default value to false. +
  • +
    +

    + At this point, you have defined a table with columns, which essentially creates the + blueprint for the Tasks table. +

    +

    + To now create and populate the table within the database, you need to open a transaction. +

    +
    +
    +
    + +

    + 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. +

    +

    + 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. +

    + + +

    + Navigate back to the + App.kt + file and add the following transaction function: +

    + +

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

    +

    + First, you create the tasks table using the create() method from SchemaUtils. + The SchemaUtils object holds utility methods for creating, altering, and + dropping database objects. +

    +

    + 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 + each column by using the it parameter. Exposed will translate the functions + into the following SQL queries: +

    + + INSERT INTO TASKS (COMPLETED, DESCRIPTION, "name") VALUES (FALSE, 'Go through the Get started with Exposed tutorial', 'Learn Exposed') + + INSERT INTO TASKS (COMPLETED, DESCRIPTION, "name") VALUES (TRUE, 'Read the first two chapters of The Hobbit', 'Read The Hobbit') + +

    + Because the insert() function returns an InsertStatement, by using + the get() method after the insert operation you retrieve the + autoincremented id value of the newly added row. +

    +

    + With the select() extension function you then create a query to count the number + 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 + column, which means it will aggregate the rows based on whether they are completed or not. + The expected SQL query looks like this: +

    + + SELECT COUNT(TASKS.ID), TASKS.COMPLETED FROM TASKS GROUP BY TASKS.COMPLETED + +

    + It is important to note that the query will not be executed until you call a function that + iterates through the result, such as forEach(). In this example, for each group + we print out the isCompleted status and the corresponding count of tasks. +

    +
    +
    +

    + 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. +

    +
    + +

    + At the beginning of your transaction block, add the following line to enable SQL query logging: +

    + +
    + + +

    + 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: +

    + + SQL: SELECT VALUE FROM INFORMATION_SCHEMA.SETTINGS WHERE NAME = 'MODE' + SQL: CREATE TABLE IF NOT EXISTS TASKS (ID INT AUTO_INCREMENT NOT NULL, "name" VARCHAR(128) NOT NULL, DESCRIPTION VARCHAR(128) NOT NULL, COMPLETED BOOLEAN DEFAULT FALSE NOT NULL) + SQL: INSERT INTO TASKS (COMPLETED, DESCRIPTION, "name") VALUES (FALSE, 'Go through the Get started with Exposed tutorial', 'Learn Exposed') + SQL: INSERT INTO TASKS (COMPLETED, DESCRIPTION, "name") VALUES (TRUE, 'Read the first two chapters of The Hobbit', 'Read The Hobbit') + Created new tasks with ids 1 and 2. + SQL: SELECT COUNT(TASKS.ID), TASKS.COMPLETED FROM TASKS GROUP BY TASKS.COMPLETED + false: 1 + true: 1 + + Process finished with exit code 0 + +
    + +

    Let’s extend the app’s functionality by updating and deleting the same task.

    + + +

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

    + +

    Here's the breakdown:

    +

    + In the Tasks.update() function, you specify the condition to find the task + with id equal to the one of the previously inserted task. If the condition is met, + the isCompleted field of the found task is set to true. +

    + +

    + Unlike the insert() function, update() returns the number of updated rows. + To then retrieve the updated task, you use the select() function + with the where condition to only select the tasks with id + equal to taskId. +

    + +

    + Using the single() extension function + initiates the statement and retrieves the first result found. +

    +

    + 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. +

    +
    + +

    + + You should now see the following result:

    + + SQL: SELECT VALUE FROM INFORMATION_SCHEMA.SETTINGS WHERE NAME = 'MODE' + SQL: CREATE TABLE IF NOT EXISTS TASKS (ID INT AUTO_INCREMENT NOT NULL, "name" VARCHAR(128) NOT NULL, DESCRIPTION VARCHAR(128) NOT NULL, COMPLETED BOOLEAN DEFAULT FALSE NOT NULL) + SQL: INSERT INTO TASKS (COMPLETED, DESCRIPTION, "name") VALUES (FALSE, 'Go through the Get started with Exposed tutorial', 'Learn Exposed') + SQL: INSERT INTO TASKS (COMPLETED, DESCRIPTION, "name") VALUES (TRUE, 'Read the first two chapters of The Hobbit', 'Read The Hobbit') + Created new tasks with ids 1 and 2. + SQL: SELECT COUNT(TASKS.ID), TASKS.COMPLETED FROM TASKS GROUP BY TASKS.COMPLETED + false: 1 + true: 1 + SQL: UPDATE TASKS SET COMPLETED=TRUE WHERE TASKS.ID = 1 + SQL: SELECT TASKS.COMPLETED FROM TASKS WHERE TASKS.ID = 1 + Updated task details: Tasks.completed=true + SQL: DELETE FROM TASKS WHERE TASKS.ID = 2 + SQL: SELECT TASKS.ID, TASKS."name", TASKS.DESCRIPTION, TASKS.COMPLETED FROM TASKS + Remaining tasks: [Tasks.id=1, Tasks.name=Learn Exposed, Tasks.description=Go through the Get started with Exposed tutorial, Tasks.completed=true] + + Process finished with exit code 0 + +
    +
    + + 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 + expected behavior in H2 databases when managing connections and transactions. +

    + To keep the database open, add ;DB_CLOSE_DELAY=-1 to the database URL: +

    + + Database.connect("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1", driver = "org.h2.Driver") + +
    +
    + + + +

    + Great job! You have now implemented a simple console application that uses Exposed to fetch and modify + task data from an in-memory database. Now that you’ve covered the basics, you are ready to + dive deep into the DSL API. +

    +
    +
    diff --git a/documentation-website/Writerside/topics/Home.topic b/documentation-website/Writerside/topics/Home.topic index cee2c33324..f2fcfbb12b 100644 --- a/documentation-website/Writerside/topics/Home.topic +++ b/documentation-website/Writerside/topics/Home.topic @@ -14,7 +14,7 @@ - Getting Started with Exposed @@ -51,4 +51,4 @@ - \ No newline at end of file + diff --git a/documentation-website/Writerside/topics/lib.topic b/documentation-website/Writerside/topics/lib.topic new file mode 100644 index 0000000000..10b9f181ae --- /dev/null +++ b/documentation-website/Writerside/topics/lib.topic @@ -0,0 +1,40 @@ + + + + + +

    + Code example: + + %example_name% + +

    +
    + + +

    + In IntelliJ IDEA, click the rerun button (intelliJ IDEA rerun icon) to restart the + application. +

    +
    + + +

    In IntelliJ IDEA, click on the run button + (intelliJ IDEA run icon) + to start the application.

    +
    + + +

    In intelliJ IDEA, click on the notification Gradle icon + (intelliJ IDEA gradle icon) + on the right side of the editor to load Gradle changes.

    +
    +
    diff --git a/documentation-website/Writerside/v.list b/documentation-website/Writerside/v.list index bdf1b0e432..d1bbe8c004 100644 --- a/documentation-website/Writerside/v.list +++ b/documentation-website/Writerside/v.list @@ -2,4 +2,6 @@ + + diff --git a/documentation-website/Writerside/writerside.cfg b/documentation-website/Writerside/writerside.cfg index 897acde806..bb587aec06 100644 --- a/documentation-website/Writerside/writerside.cfg +++ b/documentation-website/Writerside/writerside.cfg @@ -3,7 +3,7 @@ - +