Minimales Beispiel einer Maven-Kotlin-Querydsl-Integration
Veröffentlicht
Abhängigkeiten auf neue Versionen aktualisiert
Inhalt
QueryDSL ist ein praktisches Werkzeug für das Vereinfachen von Datenbankzugriffen in JVM-Programmen. In diesem Beispiel habe ich QueryDSL in ein Kotlin-basiertes Spring Boot Projekt mit Maven eingebaut.
Der Code ist verfügbar auf Github
Vorraussetzungen
Für dieses Beispiel habe ich ein Projekt mithilfe des Spring Initilizr generiert und Kotlin und JPA Module ausgewählt.
Füge die aktuelle QueryDSL Bibliothek zur pom.xml hinzu.
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-jpa</artifactId>
<version>4.3.1</version>
</dependency>
Das Entity
Ich brauchte ein simples Entity welches ich zum Testen der Generierung der Q-Klassen von QueryDSL verwende. Dafür habe ich den Kotlin data-class Syntax verwendet um ein simples JPA kompatibles Entity mit wenig Zeilen zu erstellen.
import javax.persistence.Entity
import javax.persistence.GeneratedValue
import javax.persistence.Id
@Entity
data class TestEntity (
val name: String,
val value: Double
) {
@Id @GeneratedValue
val id: Int? = null
}
Das Repository
Spring Data bietet einfache Möglichkeiten zum Zugriff auf Datenbank-Entities via Repositories, die dann auch QueryDSL Support haben.
import org.springframework.data.querydsl.QuerydslPredicateExecutor
import org.springframework.data.repository.CrudRepository
interface TestEntityRepository:
CrudRepository<TestEntity, Int>,
QuerydslPredicateExecutor<TestEntity>
Der QuerydslPredicateExecutor definiert welches Entity wir benutzen um unsere fortgeschrittenen Datenbankabfragen zu formulieren.
Die Konsumenten
Ich habe einen einfachen Service erstellt in welchen das Repository mit Dependency-Injection injiziert wird. Der Service wird nicht benutzt sondern dient dazu beim Kompilieren eine Verwendung der Q-Klassen zu generieren. Wenn die Q-Klassen zur Zeit des Kompilierens nicht generiert waren gibt es einen Fehler. Normalerweise würde erst der Test die Q-Klassen verwenden und es könnte sein dass die Q-Klassen-Generierung zwischen die compile und test-compile Maven-Phasen rutschen, das wiederum zurfolge hätte dass die Klassen zur normalen Kompilierzeit nicht zur Verfügung stehen.
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
@Service
class TestEntityService @Autowired constructor(
private val testEntityRepository: TestEntityRepository
){
fun getTestEntityByName(name: String): TestEntity? {
return testEntityRepository.findOne(
QTestEntity.testEntity.name.eq(name)
).get()
}
}
Zusätzlich habe ich einen Test erstellt der den QueryDSL Support auf einer H2-Datenbank testet.
import junit.framework.TestCase.assertEquals
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.context.junit4.SpringRunner
@RunWith(SpringRunner::class)
@SpringBootTest
class TestEntityRepositoryTest {
@Autowired
private lateinit var testEntityRepository: TestEntityRepository
@Before
fun setup() {
testEntityRepository.save(TestEntity("test", 8.0))
}
@Test
fun test() {
val testEntities = testEntityRepository.findAll()
assertEquals(1, testEntities.count())
}
}
Änderungen am Maven-Skript
Ich musste die Maven-Plugins so anpassen, dass der Kotlin Annotation Processor mit QueryDSL die Q-Klassen generiert bevor der Rest des Programms kompiliert wird.
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<configuration>
<compilerPlugins>
<plugin>jpa</plugin>
<plugin>spring</plugin>
</compilerPlugins>
<args>
<arg>-Xjsr305=strict</arg>
</args>
</configuration>
<executions>
<execution>
<id>compile</id>
<phase>process-sources</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>kapt</id>
<phase>generate-sources</phase>
<goals>
<goal>kapt</goal>
</goals>
<configuration>
<sourceDirs>
<sourceDir>src/main/kotlin</sourceDir>
</sourceDirs>
<annotationProcessorPaths>
<annotationProcessorPath>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
<version>${querydsl.version}</version>
<classifier>jpa</classifier>
</annotationProcessorPath>
</annotationProcessorPaths>
</configuration>
</execution>
<execution>
<id>test-compile</id>
<phase>test-compile</phase>
<goals>
<goal>test-compile</goal>
</goals>
<configuration>
<sourceDirs>
<sourceDir>src/test/kotlin</sourceDir>
<sourceDir>target/generated-sources/kapt/test</sourceDir>
</sourceDirs>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-noarg</artifactId>
<version>${kotlin.version}</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-allopen</artifactId>
<version>${kotlin.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
Das wars! Nach diesen Änderungen kann man QueryDSL mit Spring-Data-Repositories benutzen. Der Test sichert die Integration ab und bietet ein kleines Beispiel der Benutzung.