Hello World with Micronaut + Kotlin Extend the previous project and try connecting to the database using MyBatis.
The repository actually created is here.
Prepare a PostgreSQL container with Docker. I created the following in the same hierarchy as the project created last time.
Docker-compose.yml
for creating DB environmentdocker-compose.yml
version: '3'
services:
db:
image: postgres
restart: always
container_name: postgres
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: books
volumes:
- ./data/postgres/db-data:/var/lib/postgresql/data
- ./database:/docker-entrypoint-initdb.d
ports:
- 5432:5432
data
folder and SQL to store SQL for table creationdatabase/init.sql
set client_encoding = 'UTF8';
CREATE TABLE book (
id SERIAL,
name VARCHAR(200) NOT NULL,
publisher VARCHAR(200),
publication_date DATE,
created_at TIMESTAMP NOT NULL,
updated_at TIMESTAMP NOT NULL,
CONSTRAINT pk_book PRIMARY KEY (id)
);
--Initial data for confirmation
INSERT INTO book (id, name, publisher, publication_date, created_at, updated_at) VALUES (1, 'Test book 1', 'Test publisher A', null, current_timestamp, current_timestamp);
INSERT INTO book (id, name, publisher, publication_date, created_at, updated_at) VALUES (2, 'Test book 2', 'Test publisher A', null, current_timestamp, current_timestamp);
.Gitignore
to remove DB data from Git management.gitignore
data
Go to the folder with docker-compose
and start the container.
$ docker-compose up -d
Now the DB is ready.
Edit build.gradle and add the library.
server/build.gradle
dependencies {
//abridgement
implementation("org.mybatis:mybatis:3.4.6")
implementation("io.micronaut.sql:micronaut-jdbc-hikari")
runtimeOnly("org.postgresql:postgresql")
//abridgement
}
Edit application.yml
.
server/src/main/resources/application.yml
micronaut:
application:
name: helloworld
#Add the following
datasources:
default:
url: jdbc:postgresql://localhost:5432/books
username: postgres
password: postgres
driverClassName: org.postgresql.Driver
mybatis:
#Specify the location to store the mapper xml file
mapper-locations: classpath:example/mapper/*.xml
configuration:
map-underscore-to-camel-case: true
default-fetch-size: 100
default-statement-timeout: 30
cache-enabled: false
Create a class to store the data obtained from DB.
server/src/main/kotlin/example/model/Book.kt
package example.model
import io.micronaut.core.annotation.Introspected
import java.sql.Date
/**
*Book data class
*/
@Introspected
data class Book(
var id: Int?,
var name: String,
var publisher: String?,
var publicationDate: Date?,
)
Create a Factory class that prepares a SqlSession.
server/src/main/kotlin/example/MybatisFactory.kt
package example
import io.micronaut.context.annotation.Factory
import org.apache.ibatis.mapping.Environment
import org.apache.ibatis.session.Configuration
import org.apache.ibatis.session.SqlSessionFactory
import org.apache.ibatis.session.SqlSessionFactoryBuilder
import org.apache.ibatis.transaction.TransactionFactory
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory
import javax.inject.Singleton
import javax.sql.DataSource
@Factory
class MybatisFactory(private val dataSource: DataSource) {
@Singleton
fun sqlSessionFactory(): SqlSessionFactory {
val transactionFactory: TransactionFactory = JdbcTransactionFactory()
val environment = Environment("dev", transactionFactory, dataSource)
val configuration = Configuration(environment)
//Specify the package to scan the mapper.
configuration.addMappers("example")
return SqlSessionFactoryBuilder().build(configuration)
}
}
Create a Mapper that will interface with SQL.
server/src/main/kotlin/example/mapper/BookMapper.kt
package example.mapper
import example.model.Book
import org.apache.ibatis.annotations.Mapper
@Mapper
interface BookMapper {
fun findById(id: Int): Book
}
The SQL body to be executed is described in XML.
server/src/main/resources/example/mapper/BookMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="example.mapper.BookMapper">
<select id="findById" resultType="example.model.Book">
SELECT
id,
name,
publisher,
publication_date
FROM book
<where>
id = #{id}
</where>
</select>
</mapper>
Create a Service class as an implementation of the interface.
server/src/main/kotlin/example/service/BookService.kt
package example.service
import example.mapper.BookMapper
import example.model.Book
import org.apache.ibatis.session.SqlSessionFactory
import javax.inject.Singleton
@Singleton
class BookService(private val sqlSessionFactory: SqlSessionFactory) : BookMapper {
override fun findById(id: Int): Book {
sqlSessionFactory.openSession().use { session ->
val bookMapper = session.getMapper(BookMapper::class.java)
return bookMapper.findById(id)
}
}
}
Create an API to access the database.
server/src/main/kotlin/example/controller/BookController.kt
package example.controller
import example.mapper.BookMapper
import example.model.Book
import io.micronaut.http.HttpResponse
import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Get
@Controller()
class BookController(private val bookMapper: BookMapper) {
/**
*Acquisition of book information.
*ID specification
*
* @param id Book ID
*
* @return HttpResponse
*/
@Get("/book/{id}")
fun readById(id: Int): HttpResponse<Book> {
return HttpResponse.ok(bookMapper.findById(id))
}
}
So far, if you access the endpoint of / book / {id}
, you can get the data.
I'll give it a try.
Run the server.
$ cd server
$ ./gradlew run
Go to http: // localhost: 8080 / book / 1
.
$ curl -X GET http://localhost:8080/book/1
{"id":1,"name":"Test book 1","publisher":"Test publisher A"}
I was able to get the data from the database.
Access a database with MyBatis
Recommended Posts