Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document how to use Spring JdbcTemplate, with multi-language examples. #2494

Merged
merged 9 commits into from
Sep 18, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions doc-examples/jdbc-spring-template-example-groovy/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
plugins {
id "groovy"
id "io.micronaut.build.internal.data-example"
}

micronaut {
version libs.versions.micronaut.platform.get()
runtime "netty"
testRuntime "spock"
}

dependencies {
compileOnly projects.micronautDataProcessor
compileOnly mnValidation.micronaut.validation.processor

implementation projects.micronautDataJdbc
implementation projects.micronautDataSpringJdbc
implementation mnValidation.micronaut.validation

runtimeOnly mnSql.micronaut.jdbc.tomcat
runtimeOnly mnLogging.logback.classic
runtimeOnly mnSql.h2
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
skipDocumentation=true
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package example

import io.micronaut.context.annotation.Requires
import io.micronaut.core.annotation.NonNull
import io.micronaut.data.connection.jdbc.advice.DelegatingDataSource
import io.micronaut.data.jdbc.annotation.JdbcRepository
import io.micronaut.data.model.query.builder.sql.Dialect
import io.micronaut.data.repository.CrudRepository
import jakarta.transaction.Transactional
import jakarta.validation.Valid
import jakarta.validation.constraints.NotNull
import org.springframework.jdbc.core.JdbcTemplate

import javax.sql.DataSource

@Requires(property = 'spec.name', value = 'BookRepositorySpec')
// tag::clazz[]
@JdbcRepository(dialect = Dialect.H2)
abstract class AbstractBookRepository implements CrudRepository<@Valid Book, @NotNull Long> {

private final JdbcTemplate jdbcTemplate; //<2>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can the JdbcTemplate be injected directly without the need of instantiating it manually?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, that didn't work for me, and even in that case it did, it still needs a DataSource set before you can use it. I patterned this after what is done in: https://github.com/micronaut-projects/micronaut-data/blob/master/data-spring-jdbc/src/main/java/io/micronaut/data/spring/jdbc/SpringJdbcConnectionOperations.java

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose we could create a factory that does the same thing, and then it could be injected.


AbstractBookRepository(DataSource dataSource) { // <1>
this.jdbcTemplate = new JdbcTemplate(DelegatingDataSource.unwrapDataSource(dataSource)); //<2>
}

@Transactional
List<Book> findByTitle(@NonNull @NotNull String title) {
return jdbcTemplate.queryForList('SELECT * FROM Book AS book WHERE book.title = ?', title) // <3>
.collect(m -> new Book(m.id as Long, m.title as String, m.pages as Integer))
}
}
// end::clazz[]
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package example

import groovy.transform.Canonical
import io.micronaut.core.annotation.Nullable
import io.micronaut.data.annotation.GeneratedValue
import io.micronaut.data.annotation.Id
import io.micronaut.data.annotation.MappedEntity

@Canonical
@MappedEntity
class Book {
@Id @GeneratedValue @Nullable Long id
String title
int pages
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
datasources:
default:
url: jdbc:h2:mem:devDb;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE;NON_KEYWORDS=USER
driverClassName: org.h2.Driver
username: sa
password: ''
schema-generate: CREATE_DROP
dialect: H2
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<configuration>

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%cyan(%d{HH:mm:ss.SSS}) %gray([%thread]) %highlight(%-5level) %magenta(%logger{36}) - %msg%n</pattern>
</encoder>
</appender>

<root level="info">
<appender-ref ref="STDOUT" />
</root>
</configuration>
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package example

import io.micronaut.context.annotation.Property
import io.micronaut.test.extensions.spock.annotation.MicronautTest
import jakarta.inject.Inject
import spock.lang.Specification

@MicronautTest(transactional = false)
@Property(name = 'spec.name', value = 'BookRepositorySpec')
@Property(name = 'datasources.default.name', value = 'mydb')
@Property(name = 'datasources.default.transactionManager', value = 'springJdbc')
@Property(name = 'jpa.default.properties.hibernate.hbm2ddl.auto', value = 'create-drop')
class BookRepositorySpec extends Specification {

@Inject
AbstractBookRepository bookRepository

void "test Books JdbcTemplate"() {
given:
bookRepository.saveAll([
new Book(null, 'The Stand', 1000),
new Book(null, 'The Shining', 600),
new Book(null, 'The Power of the Dog', 500),
new Book(null, 'The Border', 700),
new Book(null, 'Along Came a Spider', 300),
new Book(null, 'Pet Cemetery', 400),
new Book(null, 'A Game of Thrones', 900),
new Book(null, 'A Clash of Kings', 1100)
])

when:
List<Book> result = bookRepository.findByTitle('The Shining')

then:
result.size() == 1

result[0].id != null
result[0].title == 'The Shining'
result[0].pages == 600

cleanup:
bookRepository.deleteAll()
}
}
22 changes: 22 additions & 0 deletions doc-examples/jdbc-spring-template-example-java/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
plugins {
id "io.micronaut.build.internal.data-example"
}

micronaut {
version libs.versions.micronaut.platform.get()
runtime "netty"
testRuntime "junit5"
}

dependencies {
annotationProcessor projects.micronautDataProcessor
annotationProcessor mnValidation.micronaut.validation.processor

implementation projects.micronautDataJdbc
implementation projects.micronautDataSpringJdbc
implementation mnValidation.micronaut.validation

runtimeOnly mnSql.micronaut.jdbc.tomcat
runtimeOnly mnLogging.logback.classic
runtimeOnly mnSql.h2
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
skipDocumentation=true
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package example;

import io.micronaut.context.annotation.Requires;
import io.micronaut.core.annotation.NonNull;
import io.micronaut.data.connection.jdbc.advice.DelegatingDataSource;
import io.micronaut.data.jdbc.annotation.JdbcRepository;
import io.micronaut.data.model.query.builder.sql.Dialect;
import io.micronaut.data.repository.CrudRepository;
import jakarta.transaction.Transactional;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import org.springframework.jdbc.core.JdbcTemplate;

import javax.sql.DataSource;
import java.util.List;

@Requires(property = "spec.name", value = "BookRepositoryTest")
// tag::clazz[]
@JdbcRepository(dialect = Dialect.H2)
public abstract class AbstractBookRepository implements CrudRepository<@Valid Book, @NotNull Long> {

private final JdbcTemplate jdbcTemplate; //<2>

public AbstractBookRepository(DataSource dataSource) { // <1>
this.jdbcTemplate = new JdbcTemplate(DelegatingDataSource.unwrapDataSource(dataSource)); //<2>
}

@Transactional
public List<Book> findByTitle(@NonNull @NotNull String title) {
return jdbcTemplate.queryForList("SELECT * FROM Book AS book WHERE book.title = ?", title) // <3>
.stream()
.map(m -> new Book((Long) m.get("id"), (String) m.get("title"), (Integer) m.get("pages")))
.toList();
}
}
// end::clazz[]
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package example;

import io.micronaut.core.annotation.Nullable;
import io.micronaut.data.annotation.GeneratedValue;
import io.micronaut.data.annotation.Id;
import io.micronaut.data.annotation.MappedEntity;

// tag::book[]
@MappedEntity
public record Book(
@Id @GeneratedValue @Nullable Long id,
String title,
int pages
) { }
// end::book[]
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
datasources:
default:
url: jdbc:h2:mem:devDb;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE;NON_KEYWORDS=USER
driverClassName: org.h2.Driver
username: sa
password: ''
schema-generate: CREATE_DROP
dialect: H2
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<configuration>

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%cyan(%d{HH:mm:ss.SSS}) %gray([%thread]) %highlight(%-5level) %magenta(%logger{36}) - %msg%n</pattern>
</encoder>
</appender>

<root level="info">
<appender-ref ref="STDOUT" />
</root>
</configuration>
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package example;

import io.micronaut.context.annotation.Property;
import io.micronaut.test.extensions.junit5.annotation.MicronautTest;
import jakarta.inject.Inject;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;

import java.util.Arrays;
import java.util.List;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;

@MicronautTest
@Property(name = "spec.name", value = "BookRepositoryTest")
@Property(name = "datasources.default.name", value = "mydb")
@Property(name = "datasources.default.transactionManager", value = "springJdbc")
@Property(name = "jpa.default.properties.hibernate.hbm2ddl.auto", value = "create-drop")
class BookRepositoryTest {

@Inject
AbstractBookRepository bookRepository;

@AfterEach
void cleanup() {
bookRepository.deleteAll();
}

@Test
void testBooksJdbcTemplate() {
bookRepository.saveAll(Arrays.asList(
new Book(null,"The Stand", 1000),
new Book(null,"The Shining", 600),
new Book(null,"The Power of the Dog", 500),
new Book(null,"The Border", 700),
new Book(null,"Along Came a Spider", 300),
new Book(null,"Pet Cemetery", 400),
new Book(null,"A Game of Thrones", 900),
new Book(null,"A Clash of Kings", 1100)
));

List<Book> result = bookRepository.findByTitle("The Shining");
assertEquals(1, result.size());

assertNotNull(result.get(0).id());
assertEquals("The Shining", result.get(0).title());
assertEquals(600, result.get(0).pages());
}
}
25 changes: 25 additions & 0 deletions doc-examples/jdbc-spring-template-example-kotlin/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
plugins {
id "org.jetbrains.kotlin.jvm"
id "org.jetbrains.kotlin.kapt"
id "org.jetbrains.kotlin.plugin.allopen"
id "io.micronaut.build.internal.data-kotlin-example"
}

micronaut {
version libs.versions.micronaut.platform.get()
runtime "netty"
testRuntime "junit5"
}

dependencies {
kapt projects.micronautDataProcessor
kapt mnValidation.micronaut.validation.processor

implementation projects.micronautDataJdbc
implementation projects.micronautDataSpringJdbc
implementation mnValidation.micronaut.validation

runtimeOnly mnSql.micronaut.jdbc.tomcat
runtimeOnly mnLogging.logback.classic
runtimeOnly mnSql.h2
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
skipDocumentation=true
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package example

import io.micronaut.context.annotation.Requires
import io.micronaut.data.connection.jdbc.advice.DelegatingDataSource
import io.micronaut.data.jdbc.annotation.JdbcRepository
import io.micronaut.data.model.query.builder.sql.Dialect
import io.micronaut.data.repository.CrudRepository
import jakarta.transaction.Transactional
import jakarta.validation.Valid
import javax.sql.DataSource
import org.springframework.jdbc.core.JdbcTemplate

@Requires(property = "spec.name", value = "BookRepositoryTest") // tag::clazz[]
// tag::clazz[]
@JdbcRepository(dialect = Dialect.H2)
abstract class AbstractBookRepository(dataSource: DataSource) : CrudRepository<@Valid Book, Long> { // <1>

private val jdbcTemplate: JdbcTemplate = JdbcTemplate(DelegatingDataSource.unwrapDataSource(dataSource)) //<2>

@Transactional
open fun findByTitle(title: String) = jdbcTemplate
.queryForList("SELECT * FROM Book AS book WHERE book.title = ?", title) // <3>
.map { m -> Book(m["id"] as Long, m["title"] as String, m["pages"] as Int) }
}
// end::clazz[]
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package example

import io.micronaut.data.annotation.GeneratedValue
import io.micronaut.data.annotation.Id
import io.micronaut.data.annotation.MappedEntity

// tag::book[]
@MappedEntity
data class Book(
@field:Id @field:GeneratedValue val id: Long?,
val title: String,
val pages: Int
)
// end::book[]
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
datasources:
default:
url: jdbc:h2:mem:devDb;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE;NON_KEYWORDS=USER
driverClassName: org.h2.Driver
username: sa
password: ''
schema-generate: CREATE_DROP
dialect: H2
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<configuration>

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%cyan(%d{HH:mm:ss.SSS}) %gray([%thread]) %highlight(%-5level) %magenta(%logger{36}) - %msg%n</pattern>
</encoder>
</appender>

<root level="info">
<appender-ref ref="STDOUT" />
</root>
</configuration>
Loading