iT邦幫忙

2021 iThome 鐵人賽

DAY 21
0
Modern Web

使用 Kotlin 快速開發 Web 程式 -- Vaadin系列 第 21

vok-orm 自訂sql 查詢 / db connection - day21

目標

延續前例
查詢指定學期成績,並且按平均進行排序,如下圖
https://ithelp.ithome.com.tw/upload/images/20211007/20138680z5ekirtvuX.png

本範例資料表

create TABLE Student(
  id bigint auto_increment PRIMARY KEY,
  name VARCHAR(200) NOT NULL,
  birthday DATE,
  created TIMESTAMP,
  gender VARCHAR(20) NOT NULL,
  height DOUBLE NOT NULL,
  weight DOUBLE NOT NULL,
  student_id VARCHAR(20),
  photo VARCHAR(100)
);

create TABLE Grade(
 id bigint auto_increment PRIMARY KEY,
 mandarin DOUBLE NOT NULL,
 description VARCHAR(50) NOT NULL,
 english DOUBLE NOT NULL,
 math DOUBLE NOT NULL,
 pe DOUBLE NOT NULL,
 student_id bigint not null REFERENCES Student(id)
)

Vaadin 的 SQL 查詢

資料庫連線

前述範例中 VoK 能夠將資料表映射到實體類,因為在Bootstrap.kt已經設定好資料庫連線,在此使用Hikari-CP管理JDB資料庫連接池 (connection pool)。

    val cfg = HikariConfig().apply {
        driverClassName = Driver::class.java.name
        jdbcUrl = "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1"
        username = "sa"
        password = ""
    }
    VaadinOnKotlin.dataSource = HikariDataSource(cfg)

設定好 jdbc url 並 setDataSource 初始化 connection pool後,只要使用db{}即可取得資料庫連線,如下所示:

db {
    handle.createQuery("select distinct description from Grade")
        .mapTo(String::class.java)
        .list()
}

刪除/新增/修改

vok-orm 提供了可直接執行SQL的彈性作法,一般而言,單一表單CRUD較傾向使用KEntity所提供的save()create()delete()validate()等方法,當上述方法皆無法達成目的時,即會採用此法。

範例 :

db {
    handle.createQuery("create TABLE CATEGORY (id bigint auto_increment PRIMARY KEY, name varchar(200) NOT NULL );").executeUpdate()
}
db {
    (0..100).forEach { Category(name = "cat $it").save() }
}
db {
    handle.createUpdate("delete from Category where id = :id")
        .bind("id", id)
        .execute()
}

查詢已上傳成績之學期

查學期

成績資料表 Grade 為實體映射類(Entity),可直接使用db{} 從connection pool取得 connection。
Grade加入一靜態方法getSemester(),請開啟Grade.kt

data class Grade(
    override var id: Long? = null,
    var student_id: Long? = null,
    var description: String? = null,
    var english: Double? = null,
    var math: Double? = null,
    var mandarin:Double? = null,
    var pe: Double? = null
): KEntity<Long> {
    companion object: Dao<Grade, Long>(Grade::class.java){
        fun getSemester(): List<String> = db {
            handle.createQuery("select distinct description from Grade")
                .mapTo(String::class.java)
                .list()
        }
    }
    val student: Student?
        get() = student_id?.let { Student.getById(student_id!!)} ?: null
}

因僅查詢description欄位,使用mapTo()方法將結果映射為字串型態List

ComboBox 顯示查詢結果

    comboBox<String>("學期"){
        setItems(Grade.getSemester())
        addValueChangeListener {
            semester = value
        }
    }

上一篇
Dialog 關閉後更新 Grid 資料 / 顯示儲存的圖檔 - day20
下一篇
如何讓 Grid 顯示關聯式 SQL 查詢的資料 - day22
系列文
使用 Kotlin 快速開發 Web 程式 -- Vaadin30

尚未有邦友留言

立即登入留言