将 Scala Slick 与数据库枚举一起使用
Using Scala Slick with database enums
使用 Slick 3 和 PostgreSQL,我需要查询和更新具有枚举类型列的 table:
create type WeekDay as ENUM('sun','mon','tue','wed','thu','fri','sat');
create table shifts(
id serial PRIMARY KEY,
user_id INTEGER,
branch_id INTEGER,
start INTEGER,
duration INTEGER,
day WeekDay
-- foreign keys etc.
);
我尝试使用 Slick 的 MappedColumnType[java.time.DayOfWeek,String]
,但这不满足 Postgres 的类型检查器(TBH,正确):
org.postgresql.util.PSQLException: ERROR: column "day" is of type weekday but expression is of type character varying
Hint: You will need to rewrite or cast the expression.
Position: 92
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2412)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2125)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:297)
at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:428)
at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:354)
at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:169)
at org.postgresql.jdbc.PgPreparedStatement.executeUpdate(PgPreparedStatement.java:136)
at com.zaxxer.hikari.pool.ProxyPreparedStatement.executeUpdate(ProxyPreparedStatement.java:61)
at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.executeUpdate(HikariProxyPreparedStatement.java)
at slick.jdbc.JdbcActionComponent$InsertActionComposerImpl$SingleInsertAction.$anonfun$run(JdbcActionComponent.scala:520)
Table class:
class ShiftTable(tag:Tag) extends Table[Shift](tag, "shifts") {
import Mappers.dayOfWeekMapper
def id = column[Long]("id", O.AutoInc, O.PrimaryKey)
def userId = column[Long]("user_id")
def branchId = column[Long]("branch_id")
def start = column[Int]("start")
def duration = column[Int]("duration")
def day = column[DayOfWeek]("day") // <- problematic column
// keys etc/
def * = (id, userId, branchId, start, duration, day) <> (Shift.tupled, Shift.unapply)
}
如何将 Scala 值映射到自定义 PostgreSQL 类型?
看起来您可以使用不使用 pg-slick 的字符串映射到枚举。
诀窍是向数据库添加强制转换,如 PG JDBC Issue 1420:
中所述
CREATE CAST (character varying AS WeekDay) WITH INOUT AS ASSIGNMENT
documentation for CAST 描述了 WITH INOUT
(避免编写用于转换的函数)和 AS ASSIGNMENT
(在赋值时隐式应用转换)。
然后您可以使用 MappedColumnType.base[java.time.DayOfWeek, String]
来定义从列到 DayOfWeek
的映射。
我在这里放了一个可运行的例子:https://github.com/d6y/pg-enum/blob/master/src/main/scala/main.scala
使用 Slick 3 和 PostgreSQL,我需要查询和更新具有枚举类型列的 table:
create type WeekDay as ENUM('sun','mon','tue','wed','thu','fri','sat');
create table shifts(
id serial PRIMARY KEY,
user_id INTEGER,
branch_id INTEGER,
start INTEGER,
duration INTEGER,
day WeekDay
-- foreign keys etc.
);
我尝试使用 Slick 的 MappedColumnType[java.time.DayOfWeek,String]
,但这不满足 Postgres 的类型检查器(TBH,正确):
org.postgresql.util.PSQLException: ERROR: column "day" is of type weekday but expression is of type character varying
Hint: You will need to rewrite or cast the expression.
Position: 92
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2412)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2125)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:297)
at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:428)
at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:354)
at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:169)
at org.postgresql.jdbc.PgPreparedStatement.executeUpdate(PgPreparedStatement.java:136)
at com.zaxxer.hikari.pool.ProxyPreparedStatement.executeUpdate(ProxyPreparedStatement.java:61)
at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.executeUpdate(HikariProxyPreparedStatement.java)
at slick.jdbc.JdbcActionComponent$InsertActionComposerImpl$SingleInsertAction.$anonfun$run(JdbcActionComponent.scala:520)
Table class:
class ShiftTable(tag:Tag) extends Table[Shift](tag, "shifts") {
import Mappers.dayOfWeekMapper
def id = column[Long]("id", O.AutoInc, O.PrimaryKey)
def userId = column[Long]("user_id")
def branchId = column[Long]("branch_id")
def start = column[Int]("start")
def duration = column[Int]("duration")
def day = column[DayOfWeek]("day") // <- problematic column
// keys etc/
def * = (id, userId, branchId, start, duration, day) <> (Shift.tupled, Shift.unapply)
}
如何将 Scala 值映射到自定义 PostgreSQL 类型?
看起来您可以使用不使用 pg-slick 的字符串映射到枚举。
诀窍是向数据库添加强制转换,如 PG JDBC Issue 1420:
中所述CREATE CAST (character varying AS WeekDay) WITH INOUT AS ASSIGNMENT
documentation for CAST 描述了 WITH INOUT
(避免编写用于转换的函数)和 AS ASSIGNMENT
(在赋值时隐式应用转换)。
然后您可以使用 MappedColumnType.base[java.time.DayOfWeek, String]
来定义从列到 DayOfWeek
的映射。
我在这里放了一个可运行的例子:https://github.com/d6y/pg-enum/blob/master/src/main/scala/main.scala