-
Scalikejdbc 를 이용해 DB 데이터 읽기scala jdbc/scalikejdbc 2021. 11. 14. 21:35
문제
MySQL test.person 테이블 스키마와 들어 있는 데이터는 아래와 같다.
CREATE table person ( name varchar(128), age INT )
name age a 10 b 20 test.person 에 저장된 데이터를 scalikejdbc 를 이용해 읽어보자
코드
build.sbt 에 아래 라이브러리를 추가한다.
libraryDependencies ++= Seq( "org.scalikejdbc" %% "scalikejdbc" % "4.0.0", "org.scalikejdbc" %% "scalikejdbc-config" % "4.0.0", "org.postgresql" % "postgresql" % "42.5.0", "mysql" % "mysql-connector-java" % "8.0.27" )
코드 작성
connectionTimeoutMillis 는 pool.borrow() timeout 값으로 필요에 따라 충분히 크게 설정한다.
poolConnectionTimeoutMillis defines the amount of time a query will wait to acquire a connection before throwing an exception. This used to be called connectionTimeoutMillis
import scalikejdbc._ case class Person(name: String, age: Int) object Person extends SQLSyntaxSupport[Person] { override def tableName: String = "person" def apply(rs: WrappedResultSet): Person = Person( rs.string("name"), rs.int("age") ) } object ScalikeTest { def main(args: Array[String]): Unit = { Class.forName("org.postgresql.Driver") // Class.forName("com.mysql.jdbc.Driver") val settings = ConnectionPoolSettings( initialSize = 4, maxSize = 20, connectionTimeoutMillis = 120000L, validationQuery = "select 1" ) ConnectionPool.singleton("jdbc:postgresql://localhost:5432/postgres", "user_id", "user_password", settings) // ConnectionPool.singleton("jdbc:mysql://db.host:3306/test", "user_id", "user_password", settings) implicit val session = AutoSession // DB.autoCommit(), DB.localTx() val entities: List[Person] = DB.readOnly(implicit session => sql"select * from person".map(rs => Person(rs)).list().apply()) // val entities: List[Person] = sql"select * from person".map(rs => Person(rs)).list().apply() for { e <- entities } println(s"${e.name} ${e.age}") } }
출력 결과
a 10
b 20설명
val name = "Alice" val personAge: Option[Int] = DB.readOnly { implicit session => sql"select age from person where name = ${name}" // don't worry, prevents SQL injection .map(rs => rs.int("age")) // extracts values from rich java.sql.ResultSet .single // single, list, traversable .apply() // Side effect!!! runs the SQL using Connection }
Internals
기본적으로 아래와 같은 구조이다.
Global object 인 ConnectionPool 에 각각의 connection pool 을 이름(예: MyPool) 과 함께 등록하고, NamedDB 로 사용한다.
import scalikejdbc._ Class.forName("...") val settings: ConnectionPoolSettings = ConnectionPoolSettings(...) ConnectionPool.add("MyPool", ..., settings) implicit val session: DBSession = NamedAutoSession("MyPool") NamedDB("MyPool").???
보통 connection pool 을 하나만 등록하기 때문에 connection pool 이름을 default 로 지정할 수 있다.
라이브러리 차원에서 connection pool 이 하나일 때 아래처럼 편히 쓰도록 지원한다. (내부적으로 pool 이름을 default 로 처리)
import scalikejdbc._ Class.forName("...") val settings: ConnectionPoolSettings = ConnectionPoolSettings(...) ConnectionPool.singleton(..., settings) // ConnectionPool.add("default", ..., settings) implicit val session: DBSession = AutoSession // implicit val session: DBSession = NamedAutoSession("default") DB.readOnly.??? // NamedDB("MyPool").readOnly.???
'scala jdbc > scalikejdbc' 카테고리의 다른 글
SQLSyntax - sqls (0) 2023.03.26 SQL string 을 실행하기 (0) 2023.03.21