-
Notifications
You must be signed in to change notification settings - Fork 211
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1639 from sgeorgakis/master
[SCALA-308]- Postgres specific features in Slick using Slick-PG
- Loading branch information
Showing
10 changed files
with
245 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
services: | ||
db: | ||
image: postgres:16.4 | ||
environment: | ||
- POSTGRES_DB=baeldung | ||
- POSTGRES_USER=baeldung | ||
- POSTGRES_PASSWORD=password | ||
ports: | ||
- '5432:5432' | ||
volumes: | ||
- baeldung-postgresql-data:/var/lib/postgresql/data | ||
|
||
volumes: | ||
baeldung-postgresql-data: |
68 changes: 68 additions & 0 deletions
68
...es-persistence/src/it/scala/com/baeldung/scala/slick_pg/BaeldungPostgresProfileSpec.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
package com.baeldung.scala.slick_pg | ||
|
||
import com.baeldung.scala.slick_pg.BaeldungPostgresProfile.api.* | ||
import com.baeldung.scala.slick_pg.entity.BaeldungEntity | ||
import com.baeldung.scala.slick_pg.table.baeldungEntityTable | ||
import com.dimafeng.testcontainers.PostgreSQLContainer | ||
import com.dimafeng.testcontainers.scalatest.TestContainerForAll | ||
import org.json4s.native.JsonMethods | ||
import org.scalatest.flatspec.AsyncFlatSpec | ||
import org.testcontainers.utility.DockerImageName | ||
import slick.dbio.DBIO | ||
|
||
import java.time.OffsetDateTime | ||
import scala.concurrent.Future | ||
|
||
class BaeldungPostgresProfileSpec | ||
extends AsyncFlatSpec | ||
with TestContainerForAll { | ||
|
||
override val containerDef: PostgreSQLContainer.Def = PostgreSQLContainer.Def( | ||
dockerImageName = DockerImageName.parse("postgres:16.4"), | ||
databaseName = "baeldung", | ||
username = "baeldung", | ||
password = "baeldung" | ||
) | ||
|
||
"BaeldungPostgresProfile" should "insert entity" in { | ||
withContainers { container => | ||
|
||
val db: BaeldungPostgresProfile.backend.Database = | ||
BaeldungPostgresProfile.backend.Database.forURL( | ||
containerDef.start().jdbcUrl, | ||
user = "baeldung", | ||
password = "baeldung", | ||
driver = "org.postgresql.Driver" | ||
) | ||
|
||
val createdAt = OffsetDateTime.now() | ||
val res = db | ||
.run( | ||
DBIO.seq( | ||
baeldungEntityTable.schema.createIfNotExists, | ||
baeldungEntityTable += BaeldungEntity( | ||
1L, | ||
createdAt, | ||
List(1d, 5d, 2.24d), | ||
JsonMethods.parse("""{"field1": 5, "field2": "test"}""") | ||
) | ||
) | ||
) | ||
.flatMap(_ => db.run(baeldungEntityTable.result)) | ||
|
||
for (sequence <- res) yield { | ||
sequence.foreach(entity => { | ||
assert(entity.id.equals(1L)) | ||
assert(entity.createdAt.equals(createdAt)) | ||
assert(entity.prices.equals(List(1d, 5d, 2.24d))) | ||
assert( | ||
entity.metadata.equals( | ||
JsonMethods.parse("""{"field1": 5, "field2": "test"}""") | ||
) | ||
) | ||
}) | ||
succeed | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
35 changes: 35 additions & 0 deletions
35
...ries-persistence/src/main/scala/com/baeldung/scala/slick_pg/BaeldungPostgresProfile.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package com.baeldung.scala.slick_pg | ||
|
||
import com.github.tminglei.slickpg.* | ||
import org.json4s.{JValue, JsonMethods} | ||
import slick.jdbc.JdbcType | ||
|
||
trait BaeldungPostgresProfile | ||
extends ExPostgresProfile | ||
with PgDate2Support | ||
with TimestamptzPostgresProfile | ||
with PgArraySupport | ||
with PgJson4sSupport { | ||
|
||
override protected def computeCapabilities: Set[slick.basic.Capability] = | ||
super.computeCapabilities + slick.jdbc.JdbcCapabilities.insertOrUpdate | ||
|
||
override val api = BaeldungApi | ||
|
||
override val pgjson = "jsonb" | ||
type DOCType = org.json4s.native.Document | ||
override val jsonMethods = | ||
org.json4s.native.JsonMethods.asInstanceOf[JsonMethods[DOCType]] | ||
|
||
object BaeldungApi | ||
extends ExtPostgresAPI | ||
with Date2DateTimeImplicitsDuration | ||
with ArrayImplicits | ||
with JsonImplicits { | ||
|
||
implicit val doubleListTypeMapper: JdbcType[List[Double]] = | ||
new SimpleArrayJdbcType[Double]("DOUBLE PRECISION").to(_.toList) | ||
} | ||
} | ||
|
||
object BaeldungPostgresProfile extends BaeldungPostgresProfile |
10 changes: 10 additions & 0 deletions
10
...libraries-persistence/src/main/scala/com/baeldung/scala/slick_pg/PostgresConnection.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package com.baeldung.scala.slick_pg | ||
|
||
import com.baeldung.scala.slick_pg | ||
import com.baeldung.scala.slick_pg.BaeldungPostgresProfile.api.* | ||
|
||
object PostgresConnection { | ||
|
||
val db: slick_pg.BaeldungPostgresProfile.backend.Database = | ||
Database.forConfig("postgres") | ||
} |
56 changes: 56 additions & 0 deletions
56
...s-persistence/src/main/scala/com/baeldung/scala/slick_pg/TimestamptzPostgresProfile.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
package com.baeldung.scala.slick_pg | ||
|
||
import slick.jdbc.PostgresProfile | ||
|
||
import java.sql.{PreparedStatement, ResultSet} | ||
import java.time.OffsetDateTime | ||
import java.time.format.DateTimeFormatterBuilder | ||
import java.time.format.DateTimeFormatter | ||
import java.time.temporal.ChronoField | ||
|
||
trait TimestamptzPostgresProfile extends PostgresProfile { | ||
|
||
override val columnTypes: PostgresJdbcTypes = new PostgresJdbcTypes { | ||
|
||
override val offsetDateTimeType: OffsetDateTimeJdbcType = | ||
new OffsetDateTimeJdbcType { | ||
|
||
override def sqlType: Int = { | ||
java.sql.Types.TIMESTAMP_WITH_TIMEZONE | ||
} | ||
|
||
private val formatter = { | ||
new DateTimeFormatterBuilder() | ||
.append(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) | ||
.optionalStart() | ||
.appendFraction(ChronoField.NANO_OF_SECOND, 0, 6, true) | ||
.optionalEnd() | ||
.optionalStart() | ||
.appendOffset("+HH:mm:ss", "+00") | ||
.optionalEnd() | ||
.toFormatter() | ||
} | ||
|
||
override def setValue( | ||
v: OffsetDateTime, | ||
p: PreparedStatement, | ||
idx: Int | ||
): Unit = { | ||
p.setObject(idx, v) | ||
} | ||
override def getValue(r: ResultSet, idx: Int): OffsetDateTime = { | ||
r.getString(idx) match { | ||
case null => null | ||
case date: String => OffsetDateTime.from(formatter.parse(date)) | ||
} | ||
} | ||
override def updateValue( | ||
v: OffsetDateTime, | ||
r: ResultSet, | ||
idx: Int | ||
): Unit = { | ||
r.updateObject(idx, v) | ||
} | ||
} | ||
} | ||
} |
12 changes: 12 additions & 0 deletions
12
...raries-persistence/src/main/scala/com/baeldung/scala/slick_pg/entity/BaeldungEntity.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package com.baeldung.scala.slick_pg.entity | ||
|
||
import org.json4s.JValue | ||
|
||
import java.time.OffsetDateTime | ||
|
||
case class BaeldungEntity( | ||
id: Long, | ||
createdAt: OffsetDateTime, | ||
prices: List[Double], | ||
metadata: JValue | ||
) |
21 changes: 21 additions & 0 deletions
21
...es-persistence/src/main/scala/com/baeldung/scala/slick_pg/table/BaeldungEntityTable.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package com.baeldung.scala.slick_pg.table | ||
|
||
import com.baeldung.scala.slick_pg.BaeldungPostgresProfile.BaeldungApi.* | ||
import com.baeldung.scala.slick_pg.entity.BaeldungEntity | ||
import org.json4s.JValue | ||
|
||
import java.time.OffsetDateTime | ||
|
||
class BaeldungEntityTable(tag: Tag) | ||
extends Table[BaeldungEntity](tag, None, "baeldung_entity") { | ||
|
||
val id = column[Long]("id", O.PrimaryKey, O.AutoInc, O.SqlType("BIGSERIAL")) | ||
val createdAt = column[OffsetDateTime]("created_at", O.SqlType("TIMESTAMPTZ")) | ||
val prices = column[List[Double]]("prices", O.SqlType("DOUBLE PRECISION[]")) | ||
val metadata = column[JValue]("metadata", O.SqlType("JSONB")) | ||
|
||
override def * = (id, createdAt, prices, metadata).mapTo[BaeldungEntity] | ||
|
||
} | ||
|
||
val baeldungEntityTable = TableQuery[BaeldungEntityTable] |