Skip to content

Commit b008284

Browse files
authored
doc: how to use Spring JdbcTemplate, with multi-language examples. (#2494)
close #2423
1 parent 60b6e7c commit b008284

File tree

23 files changed

+442
-1
lines changed

23 files changed

+442
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
plugins {
2+
id "groovy"
3+
id "io.micronaut.build.internal.data-example"
4+
}
5+
6+
micronaut {
7+
version libs.versions.micronaut.platform.get()
8+
runtime "netty"
9+
testRuntime "spock"
10+
}
11+
12+
dependencies {
13+
compileOnly projects.micronautDataProcessor
14+
compileOnly mnValidation.micronaut.validation.processor
15+
16+
implementation projects.micronautDataJdbc
17+
implementation projects.micronautDataSpringJdbc
18+
implementation mnValidation.micronaut.validation
19+
20+
runtimeOnly mnSql.micronaut.jdbc.tomcat
21+
runtimeOnly mnLogging.logback.classic
22+
runtimeOnly mnSql.h2
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
skipDocumentation=true
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package example
2+
3+
import io.micronaut.context.annotation.Requires
4+
import io.micronaut.core.annotation.NonNull
5+
import io.micronaut.data.connection.jdbc.advice.DelegatingDataSource
6+
import io.micronaut.data.jdbc.annotation.JdbcRepository
7+
import io.micronaut.data.model.query.builder.sql.Dialect
8+
import io.micronaut.data.repository.CrudRepository
9+
import jakarta.transaction.Transactional
10+
import jakarta.validation.Valid
11+
import jakarta.validation.constraints.NotNull
12+
import org.springframework.jdbc.core.JdbcTemplate
13+
14+
import javax.sql.DataSource
15+
16+
@Requires(property = 'spec.name', value = 'BookRepositorySpec')
17+
// tag::clazz[]
18+
@JdbcRepository(dialect = Dialect.H2)
19+
abstract class AbstractBookRepository implements CrudRepository<@Valid Book, @NotNull Long> {
20+
21+
private final JdbcTemplate jdbcTemplate; //<2>
22+
23+
AbstractBookRepository(DataSource dataSource) { // <1>
24+
this.jdbcTemplate = new JdbcTemplate(DelegatingDataSource.unwrapDataSource(dataSource)); //<2>
25+
}
26+
27+
@Transactional
28+
List<Book> findByTitle(@NonNull @NotNull String title) {
29+
return jdbcTemplate.queryForList('SELECT * FROM Book AS book WHERE book.title = ?', title) // <3>
30+
.collect(m -> new Book(m.id as Long, m.title as String, m.pages as Integer))
31+
}
32+
}
33+
// end::clazz[]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package example
2+
3+
import groovy.transform.Canonical
4+
import io.micronaut.core.annotation.Nullable
5+
import io.micronaut.data.annotation.GeneratedValue
6+
import io.micronaut.data.annotation.Id
7+
import io.micronaut.data.annotation.MappedEntity
8+
9+
@Canonical
10+
@MappedEntity
11+
class Book {
12+
@Id @GeneratedValue @Nullable Long id
13+
String title
14+
int pages
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
datasources:
2+
default:
3+
url: jdbc:h2:mem:devDb;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE;NON_KEYWORDS=USER
4+
driverClassName: org.h2.Driver
5+
username: sa
6+
password: ''
7+
schema-generate: CREATE_DROP
8+
dialect: H2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<configuration>
2+
3+
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
4+
<encoder>
5+
<pattern>%cyan(%d{HH:mm:ss.SSS}) %gray([%thread]) %highlight(%-5level) %magenta(%logger{36}) - %msg%n</pattern>
6+
</encoder>
7+
</appender>
8+
9+
<root level="info">
10+
<appender-ref ref="STDOUT" />
11+
</root>
12+
</configuration>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package example
2+
3+
import io.micronaut.context.annotation.Property
4+
import io.micronaut.test.extensions.spock.annotation.MicronautTest
5+
import jakarta.inject.Inject
6+
import spock.lang.Specification
7+
8+
@MicronautTest(transactional = false)
9+
@Property(name = 'spec.name', value = 'BookRepositorySpec')
10+
@Property(name = 'datasources.default.name', value = 'mydb')
11+
@Property(name = 'datasources.default.transaction-manager', value = 'springJdbc')
12+
@Property(name = 'jpa.default.properties.hibernate.hbm2ddl.auto', value = 'create-drop')
13+
class BookRepositorySpec extends Specification {
14+
15+
@Inject
16+
AbstractBookRepository bookRepository
17+
18+
void "test Books JdbcTemplate"() {
19+
given:
20+
bookRepository.saveAll([
21+
new Book(null, 'The Stand', 1000),
22+
new Book(null, 'The Shining', 600),
23+
new Book(null, 'The Power of the Dog', 500),
24+
new Book(null, 'The Border', 700),
25+
new Book(null, 'Along Came a Spider', 300),
26+
new Book(null, 'Pet Cemetery', 400),
27+
new Book(null, 'A Game of Thrones', 900),
28+
new Book(null, 'A Clash of Kings', 1100)
29+
])
30+
31+
when:
32+
List<Book> result = bookRepository.findByTitle('The Shining')
33+
34+
then:
35+
result.size() == 1
36+
37+
result[0].id != null
38+
result[0].title == 'The Shining'
39+
result[0].pages == 600
40+
41+
cleanup:
42+
bookRepository.deleteAll()
43+
}
44+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
plugins {
2+
id "io.micronaut.build.internal.data-example"
3+
}
4+
5+
micronaut {
6+
version libs.versions.micronaut.platform.get()
7+
runtime "netty"
8+
testRuntime "junit5"
9+
}
10+
11+
dependencies {
12+
annotationProcessor projects.micronautDataProcessor
13+
annotationProcessor mnValidation.micronaut.validation.processor
14+
15+
implementation projects.micronautDataJdbc
16+
implementation projects.micronautDataSpringJdbc
17+
implementation mnValidation.micronaut.validation
18+
19+
runtimeOnly mnSql.micronaut.jdbc.tomcat
20+
runtimeOnly mnLogging.logback.classic
21+
runtimeOnly mnSql.h2
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
skipDocumentation=true
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package example;
2+
3+
import io.micronaut.context.annotation.Requires;
4+
import io.micronaut.core.annotation.NonNull;
5+
import io.micronaut.data.connection.jdbc.advice.DelegatingDataSource;
6+
import io.micronaut.data.jdbc.annotation.JdbcRepository;
7+
import io.micronaut.data.model.query.builder.sql.Dialect;
8+
import io.micronaut.data.repository.CrudRepository;
9+
import jakarta.transaction.Transactional;
10+
import jakarta.validation.Valid;
11+
import jakarta.validation.constraints.NotNull;
12+
import org.springframework.jdbc.core.JdbcTemplate;
13+
14+
import javax.sql.DataSource;
15+
import java.util.List;
16+
17+
@Requires(property = "spec.name", value = "BookRepositoryTest")
18+
// tag::clazz[]
19+
@JdbcRepository(dialect = Dialect.H2)
20+
public abstract class AbstractBookRepository implements CrudRepository<@Valid Book, @NotNull Long> {
21+
22+
private final JdbcTemplate jdbcTemplate; //<2>
23+
24+
public AbstractBookRepository(DataSource dataSource) { // <1>
25+
this.jdbcTemplate = new JdbcTemplate(DelegatingDataSource.unwrapDataSource(dataSource)); //<2>
26+
}
27+
28+
@Transactional
29+
public List<Book> findByTitle(@NonNull @NotNull String title) {
30+
return jdbcTemplate.queryForList("SELECT * FROM Book AS book WHERE book.title = ?", title) // <3>
31+
.stream()
32+
.map(m -> new Book((Long) m.get("id"), (String) m.get("title"), (Integer) m.get("pages")))
33+
.toList();
34+
}
35+
}
36+
// end::clazz[]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package example;
2+
3+
import io.micronaut.core.annotation.Nullable;
4+
import io.micronaut.data.annotation.GeneratedValue;
5+
import io.micronaut.data.annotation.Id;
6+
import io.micronaut.data.annotation.MappedEntity;
7+
8+
// tag::book[]
9+
@MappedEntity
10+
public record Book(
11+
@Id @GeneratedValue @Nullable Long id,
12+
String title,
13+
int pages
14+
) { }
15+
// end::book[]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
datasources:
2+
default:
3+
url: jdbc:h2:mem:devDb;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE;NON_KEYWORDS=USER
4+
driverClassName: org.h2.Driver
5+
username: sa
6+
password: ''
7+
schema-generate: CREATE_DROP
8+
dialect: H2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<configuration>
2+
3+
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
4+
<encoder>
5+
<pattern>%cyan(%d{HH:mm:ss.SSS}) %gray([%thread]) %highlight(%-5level) %magenta(%logger{36}) - %msg%n</pattern>
6+
</encoder>
7+
</appender>
8+
9+
<root level="info">
10+
<appender-ref ref="STDOUT" />
11+
</root>
12+
</configuration>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package example;
2+
3+
import io.micronaut.context.annotation.Property;
4+
import io.micronaut.test.extensions.junit5.annotation.MicronautTest;
5+
import jakarta.inject.Inject;
6+
import org.junit.jupiter.api.AfterEach;
7+
import org.junit.jupiter.api.Test;
8+
9+
import java.util.Arrays;
10+
import java.util.List;
11+
12+
import static org.junit.jupiter.api.Assertions.assertEquals;
13+
import static org.junit.jupiter.api.Assertions.assertNotNull;
14+
15+
@MicronautTest
16+
@Property(name = "spec.name", value = "BookRepositoryTest")
17+
@Property(name = "datasources.default.name", value = "mydb")
18+
@Property(name = "datasources.default.transaction-manager", value = "springJdbc")
19+
@Property(name = "jpa.default.properties.hibernate.hbm2ddl.auto", value = "create-drop")
20+
class BookRepositoryTest {
21+
22+
@Inject
23+
AbstractBookRepository bookRepository;
24+
25+
@AfterEach
26+
void cleanup() {
27+
bookRepository.deleteAll();
28+
}
29+
30+
@Test
31+
void testBooksJdbcTemplate() {
32+
bookRepository.saveAll(Arrays.asList(
33+
new Book(null,"The Stand", 1000),
34+
new Book(null,"The Shining", 600),
35+
new Book(null,"The Power of the Dog", 500),
36+
new Book(null,"The Border", 700),
37+
new Book(null,"Along Came a Spider", 300),
38+
new Book(null,"Pet Cemetery", 400),
39+
new Book(null,"A Game of Thrones", 900),
40+
new Book(null,"A Clash of Kings", 1100)
41+
));
42+
43+
List<Book> result = bookRepository.findByTitle("The Shining");
44+
assertEquals(1, result.size());
45+
46+
assertNotNull(result.get(0).id());
47+
assertEquals("The Shining", result.get(0).title());
48+
assertEquals(600, result.get(0).pages());
49+
}
50+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
plugins {
2+
id "org.jetbrains.kotlin.jvm"
3+
id "org.jetbrains.kotlin.kapt"
4+
id "org.jetbrains.kotlin.plugin.allopen"
5+
id "io.micronaut.build.internal.data-kotlin-example"
6+
}
7+
8+
micronaut {
9+
version libs.versions.micronaut.platform.get()
10+
runtime "netty"
11+
testRuntime "junit5"
12+
}
13+
14+
dependencies {
15+
kapt projects.micronautDataProcessor
16+
kapt mnValidation.micronaut.validation.processor
17+
18+
implementation projects.micronautDataJdbc
19+
implementation projects.micronautDataSpringJdbc
20+
implementation mnValidation.micronaut.validation
21+
22+
runtimeOnly mnSql.micronaut.jdbc.tomcat
23+
runtimeOnly mnLogging.logback.classic
24+
runtimeOnly mnSql.h2
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
skipDocumentation=true
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package example
2+
3+
import io.micronaut.context.annotation.Requires
4+
import io.micronaut.data.connection.jdbc.advice.DelegatingDataSource
5+
import io.micronaut.data.jdbc.annotation.JdbcRepository
6+
import io.micronaut.data.model.query.builder.sql.Dialect
7+
import io.micronaut.data.repository.CrudRepository
8+
import jakarta.transaction.Transactional
9+
import jakarta.validation.Valid
10+
import javax.sql.DataSource
11+
import org.springframework.jdbc.core.JdbcTemplate
12+
13+
@Requires(property = "spec.name", value = "BookRepositoryTest") // tag::clazz[]
14+
// tag::clazz[]
15+
@JdbcRepository(dialect = Dialect.H2)
16+
abstract class AbstractBookRepository(dataSource: DataSource) : CrudRepository<@Valid Book, Long> { // <1>
17+
18+
private val jdbcTemplate: JdbcTemplate = JdbcTemplate(DelegatingDataSource.unwrapDataSource(dataSource)) //<2>
19+
20+
@Transactional
21+
open fun findByTitle(title: String) = jdbcTemplate
22+
.queryForList("SELECT * FROM Book AS book WHERE book.title = ?", title) // <3>
23+
.map { m -> Book(m["id"] as Long, m["title"] as String, m["pages"] as Int) }
24+
}
25+
// end::clazz[]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package example
2+
3+
import io.micronaut.data.annotation.GeneratedValue
4+
import io.micronaut.data.annotation.Id
5+
import io.micronaut.data.annotation.MappedEntity
6+
7+
// tag::book[]
8+
@MappedEntity
9+
data class Book(
10+
@field:Id @field:GeneratedValue val id: Long?,
11+
val title: String,
12+
val pages: Int
13+
)
14+
// end::book[]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
datasources:
2+
default:
3+
url: jdbc:h2:mem:devDb;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE;NON_KEYWORDS=USER
4+
driverClassName: org.h2.Driver
5+
username: sa
6+
password: ''
7+
schema-generate: CREATE_DROP
8+
dialect: H2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<configuration>
2+
3+
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
4+
<encoder>
5+
<pattern>%cyan(%d{HH:mm:ss.SSS}) %gray([%thread]) %highlight(%-5level) %magenta(%logger{36}) - %msg%n</pattern>
6+
</encoder>
7+
</appender>
8+
9+
<root level="info">
10+
<appender-ref ref="STDOUT" />
11+
</root>
12+
</configuration>

0 commit comments

Comments
 (0)