+
+    /**
+     * Return the first 2 users ordered by their lastname asc.
+     *
+     * 
+     * Example for findFirstK / findTopK functionality.
+     * 
+     */
+    fun findFirst2ByOrderByLastnameAsc(): List
+
+    /**
+     * Return the first 2 users ordered by the given {@code sort} definition.
+     *
+     * 
+     * This variant is very flexible because one can ask for the first K results when a ASC ordering
+     * is used as well as for the last K results when a DESC ordering is used.
+     * 
+     *
+     * @param sort
+     */
+    fun findTop2By(sort: Sort): List
+
+    /**
+     * Return all the users with the given firstname or lastname. Makes use of SpEL (Spring Expression Language).
+     *
+     * @param user
+     */
+    @Query("select * from Users u where u.firstname = :#{#user.firstname} or u.lastname = :#{#user.lastname}")
+    fun findByFirstnameOrLastname(user: User): Iterable
+}
diff --git a/jdbc/spring-data-jdbc/src/main/kotlin/tech/ydb/jdbc/simple/User.kt b/jdbc/spring-data-jdbc/src/main/kotlin/tech/ydb/jdbc/simple/User.kt
new file mode 100644
index 0000000..2063f3a
--- /dev/null
+++ b/jdbc/spring-data-jdbc/src/main/kotlin/tech/ydb/jdbc/simple/User.kt
@@ -0,0 +1,53 @@
+package tech.ydb.jdbc.simple
+
+import org.springframework.data.annotation.Id
+import org.springframework.data.annotation.Transient
+import org.springframework.data.domain.Persistable
+import org.springframework.data.relational.core.mapping.Table
+import org.springframework.data.util.ProxyUtils
+import java.util.concurrent.ThreadLocalRandom
+
+@Table(name = "Users")
+class User : Persistable {
+
+    @Id
+    var id: Long = ThreadLocalRandom.current().nextLong()
+
+    lateinit var username: String
+
+    lateinit var firstname: String
+
+    lateinit var lastname: String
+
+    @Transient
+    var new = true
+
+    override fun equals(other: Any?): Boolean {
+        if (null == other) {
+            return false
+        }
+
+        if (this === other) {
+            return true
+        }
+
+        if (javaClass != ProxyUtils.getUserClass(other)) {
+            return false
+        }
+
+        val that: User = other as User
+
+        return this.id == that.id
+    }
+
+    override fun hashCode(): Int {
+        var hashCode = 17
+
+        hashCode += id.hashCode() * 31
+
+        return hashCode
+    }
+
+    override fun getId() = id
+    override fun isNew() = new
+}
diff --git a/jdbc/spring-data-jdbc/src/main/kotlin/tech/ydb/jdbc/simple/UserApplication.kt b/jdbc/spring-data-jdbc/src/main/kotlin/tech/ydb/jdbc/simple/UserApplication.kt
new file mode 100644
index 0000000..a9679a9
--- /dev/null
+++ b/jdbc/spring-data-jdbc/src/main/kotlin/tech/ydb/jdbc/simple/UserApplication.kt
@@ -0,0 +1,11 @@
+package tech.ydb.jdbc.simple
+
+import org.springframework.boot.autoconfigure.SpringBootApplication
+import org.springframework.data.jdbc.repository.config.EnableJdbcRepositories
+
+/**
+ * @author Kirill Kurdyukov
+ */
+@EnableJdbcRepositories
+@SpringBootApplication
+class UserApplication
\ No newline at end of file
diff --git a/jdbc/spring-data-jdbc/src/main/resources/application-ydb.properties b/jdbc/spring-data-jdbc/src/main/resources/application-ydb.properties
new file mode 100644
index 0000000..51e27c2
--- /dev/null
+++ b/jdbc/spring-data-jdbc/src/main/resources/application-ydb.properties
@@ -0,0 +1,4 @@
+spring.datasource.driver-class-name=tech.ydb.jdbc.YdbDriver
+spring.datasource.url=jdbc:ydb:grpc://localhost:2136/local
+
+logging.level.org.springframework.jdbc.core.JdbcTemplate=debug
\ No newline at end of file
diff --git a/jdbc/spring-data-jdbc/src/test/kotlin/tech/ydb/jdbc/YdbDockerTest.kt b/jdbc/spring-data-jdbc/src/test/kotlin/tech/ydb/jdbc/YdbDockerTest.kt
new file mode 100644
index 0000000..3293d25
--- /dev/null
+++ b/jdbc/spring-data-jdbc/src/test/kotlin/tech/ydb/jdbc/YdbDockerTest.kt
@@ -0,0 +1,29 @@
+package tech.ydb.jdbc
+
+import org.junit.jupiter.api.extension.RegisterExtension
+import org.springframework.test.context.ActiveProfiles
+import org.springframework.test.context.DynamicPropertyRegistry
+import org.springframework.test.context.DynamicPropertySource
+import tech.ydb.test.junit5.YdbHelperExtension
+
+/**
+ * @author Kirill Kurdyukov
+ */
+@ActiveProfiles("test", "ydb")
+abstract class YdbDockerTest {
+
+    companion object {
+        @JvmField
+        @RegisterExtension
+        val ydb = YdbHelperExtension()
+
+        @JvmStatic
+        @DynamicPropertySource
+        fun propertySource(registry: DynamicPropertyRegistry) {
+            registry.add("spring.datasource.url") {
+                "jdbc:ydb:${if (ydb.useTls()) "grpcs://" else "grpc://"}" +
+                        "${ydb.endpoint()}${ydb.database()}${ydb.authToken()?.let { "?token=$it" } ?: ""}"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/jdbc/spring-data-jdbc/src/test/kotlin/tech/ydb/jdbc/simple/SimpleRepositoryTest.kt b/jdbc/spring-data-jdbc/src/test/kotlin/tech/ydb/jdbc/simple/SimpleRepositoryTest.kt
new file mode 100644
index 0000000..13168ee
--- /dev/null
+++ b/jdbc/spring-data-jdbc/src/test/kotlin/tech/ydb/jdbc/simple/SimpleRepositoryTest.kt
@@ -0,0 +1,156 @@
+package tech.ydb.jdbc.simple
+
+import org.assertj.core.api.Assertions.assertThat
+import org.junit.jupiter.api.Assertions.assertNotNull
+import org.junit.jupiter.api.Assertions.assertNull
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.boot.test.context.SpringBootTest
+import org.springframework.data.domain.Limit
+import org.springframework.data.domain.PageRequest
+import org.springframework.data.domain.Sort
+import org.springframework.transaction.annotation.Transactional
+import tech.ydb.jdbc.YdbDockerTest
+
+/**
+ * @author Kirill Kurdyukov
+ */
+@SpringBootTest
+@Transactional
+class SimpleRepositoryTest : YdbDockerTest() {
+
+    @Autowired
+    lateinit var repository: SimpleUserRepository
+
+    lateinit var user: User
+
+    @BeforeEach
+    fun setUp() {
+        user = User().apply {
+            username = "foobar"
+            firstname = "firstname"
+            lastname = "lastname"
+        }
+    }
+
+    @Test
+    fun findSavedUserById() {
+        user = repository.save(user)
+
+        assertThat(repository.findById(user.id)).hasValue(user)
+    }
+
+    @Test
+    fun findSavedUserByLastname() {
+        user = repository.save(user)
+
+        assertThat(repository.findByLastname("lastname")).contains(user)
+    }
+
+    @Test
+    fun findLimitedNumberOfUsersViaDerivedQuery() {
+        (0..10).forEach { _ -> repository.save(User().apply { lastname = "lastname" }) }
+
+        assertThat(repository.findByLastname("lastname", Limit.of(5))).hasSize(5)
+    }
+
+    @Test
+    fun findLimitedNumberOfUsersViaAnnotatedQuery() {
+        (0..10).forEach { _ -> repository.save(User().apply { firstname = "firstname" }) }
+
+        assertThat(repository.findByFirstname("firstname", Limit.of(5))).hasSize(5)
+    }
+
+    @Test
+    fun findByFirstnameOrLastname() {
+        user = repository.save(user)
+
+        assertThat(repository.findByFirstnameOrLastname("lastname")).contains(user)
+    }
+
+    @Test
+    fun useOptionalAsReturnAndParameterType() {
+        assertNull(repository.findByUsername("foobar"))
+
+        repository.save(user)
+
+        assertNotNull(repository.findByUsername("foobar"))
+    }
+
+    @Test
+    fun useSliceToLoadContent() {
+        val totalNumberUsers = 11
+        val source: MutableList = ArrayList(totalNumberUsers)
+
+        for (i in 1..totalNumberUsers) {
+            val user = User().apply {
+                lastname = user.lastname
+                username = "${user.lastname}-${String.format("%03d", i)}"
+            }
+
+            source.add(user)
+        }
+
+        repository.saveAll(source)
+
+        val users = repository.findByLastnameOrderByUsernameAsc(user.lastname, PageRequest.of(1, 5))
+
+        assertThat(users).containsAll(source.subList(5, 10))
+    }
+
+    @Test
+    fun findFirst2ByOrderByLastnameAsc() {
+        val user0 = User().apply { lastname = "lastname-0" }
+
+        val user1 = User().apply { lastname = "lastname-1" }
+
+        val user2 = User().apply { lastname = "lastname-2" }
+
+        // we deliberately save the items in reverse
+        repository.saveAll(listOf(user2, user1, user0))
+
+        val result = repository.findFirst2ByOrderByLastnameAsc()
+
+        assertThat(result).containsExactly(user0, user1)
+    }
+
+    @Test
+    fun findTop2ByWithSort() {
+        val user0 = User().apply { lastname = "lastname-0" }
+
+        val user1 = User().apply { lastname = "lastname-1" }
+
+        val user2 = User().apply { lastname = "lastname-2" }
+
+        // we deliberately save the items in reverse
+        repository.saveAll(listOf(user2, user1, user0))
+
+        val resultAsc = repository.findTop2By(Sort.by(Sort.Direction.ASC, "lastname"))
+
+        assertThat(resultAsc).containsExactly(user0, user1)
+
+        val resultDesc = repository.findTop2By(Sort.by(Sort.Direction.DESC, "lastname"))
+
+        assertThat(resultDesc).containsExactly(user2, user1)
+    }
+
+    @Test
+    fun findByFirstnameOrLastnameUsingSpEL() {
+        val first = User().apply { lastname = "lastname" }
+
+        val second = User().apply { firstname = "firstname" }
+
+        val third = User()
+
+        repository.saveAll(listOf(first, second, third))
+
+        val reference = User().apply { firstname = "firstname"; lastname = "lastname" }
+
+        val users = repository.findByFirstnameOrLastname(reference)
+
+        assertThat(users).contains(first)
+        assertThat(users).contains(second)
+        assertThat(users).hasSize(2)
+    }
+}
\ No newline at end of file
diff --git a/jdbc/spring-data-jdbc/src/test/resources/application-test.properties b/jdbc/spring-data-jdbc/src/test/resources/application-test.properties
new file mode 100644
index 0000000..e69de29
diff --git a/jdbc/spring-data-jdbc/src/test/resources/db/migration/V1__create_table.sql b/jdbc/spring-data-jdbc/src/test/resources/db/migration/V1__create_table.sql
new file mode 100644
index 0000000..449db68
--- /dev/null
+++ b/jdbc/spring-data-jdbc/src/test/resources/db/migration/V1__create_table.sql
@@ -0,0 +1,9 @@
+CREATE TABLE Users
+(
+    id        Int64,
+    username  Text,
+    firstname Text,
+    lastname  Text,
+    PRIMARY KEY (id),
+    INDEX username_index GLOBAL ON (username)
+)
\ No newline at end of file