Skip to content

Commit

Permalink
Merge pull request #21 from ydb-platform/spring-data-jpa-v5-example
Browse files Browse the repository at this point in the history
Spring Data JPA 2.5.7 Example & Hibernate 5
  • Loading branch information
KirillKurdyukov authored Jan 22, 2024
2 parents 1bff0e7 + a05814e commit b08478d
Show file tree
Hide file tree
Showing 19 changed files with 818 additions and 0 deletions.
1 change: 1 addition & 0 deletions jdbc/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

<modules>
<module>basic-example</module>
<module>spring-data-jpa-v5</module>
</modules>

<dependencyManagement>
Expand Down
147 changes: 147 additions & 0 deletions jdbc/spring-data-jpa-v5/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>tech.ydb.jdbc.examples</groupId>
<artifactId>ydb-jdbc-examples</artifactId>
<version>1.1.0-SNAPSHOT</version>
</parent>

<artifactId>spring-data-jpa-v5</artifactId>
<name>Spring Data JPA Example Hibernate 5</name>
<description>Basic example for SpringBoot3 and Hibernate 6</description>
<properties>
<kotlin.version>1.9.22</kotlin.version>
<hibernate.ydb.dialect.version>0.9.1</hibernate.ydb.dialect.version>
<spring.boot.version>2.5.7</spring.boot.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>${spring.boot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-commons</artifactId>
<version>${spring.boot.version}</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-reflect</artifactId>
<version>${kotlin.version}</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>${kotlin.version}</version>
</dependency>
<dependency>
<groupId>tech.ydb.dialects</groupId>
<artifactId>hibernate-ydb-dialect-v5</artifactId>
<version>${hibernate.ydb.dialect.version}</version>
</dependency>
<dependency>
<groupId>tech.ydb.jdbc</groupId>
<artifactId>ydb-jdbc-driver-shaded</artifactId>
</dependency>
<dependency>
<groupId>com.github.javafaker</groupId>
<artifactId>javafaker</artifactId>
<version>1.0.2</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlinx</groupId>
<artifactId>kotlinx-coroutines-core</artifactId>
<version>1.7.3</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.7.1</version>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>postgresql</artifactId>
<version>1.19.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>tech.ydb.test</groupId>
<artifactId>ydb-junit5-support</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>${spring.boot.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>
<testSourceDirectory>${project.basedir}/src/test/kotlin</testSourceDirectory>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<environmentVariables>
<TESTCONTAINERS_REUSE_ENABLE>true</TESTCONTAINERS_REUSE_ENABLE>
</environmentVariables>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring.boot.version}</version>
</plugin>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>test-compile</id>
<goals>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
<configuration>
<args>
<arg>-Xjsr305=strict</arg>
</args>
<compilerPlugins>
<plugin>spring</plugin>
<plugin>jpa</plugin>
</compilerPlugins>
</configuration>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-allopen</artifactId>
<version>${kotlin.version}</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-noarg</artifactId>
<version>${kotlin.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package tech.ydb.jpa.pagination

import javax.persistence.Entity
import javax.persistence.Id
import javax.persistence.Table

@Entity
@Table(name = "authors")
class Author {

@Id
lateinit var id: String

lateinit var firstName: String

lateinit var lastName: String
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package tech.ydb.jpa.pagination

import java.util.*
import javax.persistence.*

@Entity
@Table(name = "books")
class Book {

@Id
lateinit var id: String

lateinit var title: String
lateinit var isbn10: String
lateinit var publicationDate: Date

@ManyToOne
lateinit var author: Author
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package tech.ydb.jpa.pagination

import org.springframework.data.domain.*
import org.springframework.data.jpa.repository.Query
import org.springframework.data.repository.CrudRepository
import org.springframework.data.repository.query.Param

interface BookRepository : CrudRepository<Book, String> {

/**
* Uses an offset based pagination that first sorts the entries by their [ publication_date][Book.getPublicationDate]
* and then limits the result by dropping the number of rows specified in the
* [offset][Pageable.getOffset] clause. To retrieve [Page.getTotalElements] an additional count query
* is executed.
*
* @param title
* @param pageable
*/
@Query(
"SELECT * FROM books WHERE books.title LIKE %:title% ORDER BY books.publication_date",
countQuery = "SELECT count(*) FROM books WHERE books.title LIKE %:title%",
nativeQuery = true
)
fun findByTitleContainsOrderByPublicationDate(@Param("title") title: String, pageable: Pageable): Page<Book>

/**
* Uses an offset based slicing that first sorts the entries by their [ publication_date][Book.getPublicationDate]
* and then limits the result by dropping the number of rows specified in the
* [offset][Pageable.getOffset] clause.
*
* @param title
* @param pageable
*/
@Query(
"SELECT * FROM books WHERE books.title LIKE %:title% ORDER BY books.publication_date",
nativeQuery = true
)
fun findBooksByTitleContainsOrderByPublicationDate(title: String, pageable: Pageable): Slice<Book>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package tech.ydb.jpa.pagination

import org.springframework.boot.autoconfigure.SpringBootApplication

@SpringBootApplication
class PagingApplication
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
package tech.ydb.jpa.simple;

import org.springframework.data.domain.Pageable
import org.springframework.data.domain.Slice
import org.springframework.data.jpa.repository.Query
import org.springframework.data.repository.CrudRepository
import org.springframework.scheduling.annotation.Async
import java.util.concurrent.CompletableFuture
import java.util.stream.Stream

/**
* Simple repository interface for {@link User} instances. The interface is used to declare the so-called query methods,
* i.e. methods to retrieve single entities or collections of them.
*/
interface SimpleUserRepository : CrudRepository<User, Long> {

/**
* Find the user with the given username. This method will be translated into a query using the
* {@link jakarta.persistence.NamedQuery} annotation at the {@link User} class.
*
* @param username
*/
fun findByTheUsersName(username: String): User

/**
* Uses {@link Optional} as return and parameter type.
*
* @param username
*/
fun findByUsername(username: String?): User?

/**
* Find all users with the given lastname. This method will be translated into a query by constructing it directly
* from the method name as there is no other query declared.
*
* @param lastname
*/
fun findByLastname(lastname: String): List<User>


/**
* Returns all users with the given firstname. This method will be translated into a query using the one declared in
* the {@link Query} annotation declared one.
*
* @param firstname
*/
@Query("select u from User u where u.firstname = :firstname")
fun findByFirstname(firstname: String): List<User>


/**
* Returns all users with the given name as first- or lastname. This makes the query to method relation much more
* refactoring-safe as the order of the method parameters is completely irrelevant.
*
* @param name
*/
@Query("select u from User u where u.firstname = :name or u.lastname = :name")
fun findByFirstnameOrLastname(name: String): List<User>

/**
* Returns the total number of entries deleted as their lastnames match the given one.
*
* @param lastname
* @return
*/
fun removeByLastname(lastname: String): Long

/**
* Returns a {@link Slice} counting a maximum number of {@link Pageable#getPageSize()} users matching given criteria
* starting at {@link Pageable#getOffset()} without prior count of the total number of elements available.
*
* @param lastname
* @param page
*/
@Query(
"SELECT * FROM users WHERE users.lastname = :lastname ORDER BY users.username",
nativeQuery = true
)
fun findByLastnameOrderByUsernameAsc(lastname: String, page: Pageable): Slice<User>

/**
* Return the first 2 users ordered by their lastname asc.
*
* <pre>
* Example for findFirstK / findTopK functionality.
* </pre>
*/
@Query("SELECT * FROM users ORDER BY lastname LIMIT 2", nativeQuery = true)
fun findFirst2ByOrderByLastnameAsc(): List<User>


/**
* Return all the users with the given firstname or lastname. Makes use of SpEL (Spring Expression Language).
*
* @param user
*/
@Query("select u from User u where u.firstname = :#{#user.firstname} or u.lastname = :#{#user.lastname}")
fun findByFirstnameOrLastname(user: User): Iterable<User>

/**
* Sample default method.
*
* @param user
*/
fun findByLastname(user: User): List<User> {
return findByLastname(user.lastname);
}

/**
* Sample method to demonstrate support for {@link Stream} as a return type with a custom query. The query is executed
* in a streaming fashion which means that the method returns as soon as the first results are ready.
*/
@Query("select u from User u")
fun streamAllCustomers(): Stream<User>

/**
* Sample method to demonstrate support for {@link Stream} as a return type with a derived query. The query is
* executed in a streaming fashion which means that the method returns as soon as the first results are ready.
*/
fun findAllByLastnameIsNotNull(): Stream<User>

@Async
fun readAllBy(): CompletableFuture<List<User>>
}
Loading

0 comments on commit b08478d

Please sign in to comment.