kotlin Micronaut数据JDBC:如何使用枚举Map一对多关系?

hwamh0ep  于 2023-02-05  发布在  Kotlin
关注(0)|答案(1)|浏览(124)

我想用Micronaut数据标注Map一个单向的一对多关系。考虑到下面描述的对象和数据库模型,如何用Micronaut标注Map它?
对象模型:

import io.micronaut.serde.annotation.Serdeable

@Serdeable
enum class Role {
    Admin, Manager
}
import io.micronaut.data.annotation.GeneratedValue
import io.micronaut.data.annotation.Id
import io.micronaut.data.annotation.MappedEntity
import io.micronaut.serde.annotation.Serdeable

@Serdeable
@MappedEntity
data class User(

    @field:Id
    @field:GeneratedValue
    var id: Long? = null,
    
    val username: String,

    // How to map?
    var roles: Set<Role>?
)

多对多数据库模型(PostgreSQL的DDL):

CREATE TABLE "user"
(
    id       SERIAL PRIMARY KEY,
    username VARCHAR(30) NOT NULL UNIQUE
);

CREATE TABLE "role"
(
    id INTEGER PRIMARY KEY,
    name VARCHAR(40) NOT NULL
);

CREATE TABLE "user_role"
(
    user_id INTEGER REFERENCES "user" (id),
    role_id INTEGER REFERENCES "role" (id)
);

INSERT INTO "role" (id, name) VALUES (1, 'Admin'), (2, 'Manager');

或者另一种选择,使用一对多(PostgeSQL)的更简单的数据库模型:

CREATE TABLE "user"
(
    id       SERIAL PRIMARY KEY,
    username VARCHAR(30) NOT NULL UNIQUE
);

CREATE TYPE role_name AS ENUM ('Admin', 'Manager');

CREATE TABLE "user_role"
(
    user_id INTEGER NOT NULL REFERENCES "user" (id),
    role_id INTEGER NOT NULL REFERENCES "role" (id),
    CONSTRAINT user_role_uk UNIQUE (user_id, role_id)
);

您可以建议对任何数据库模型进行修改,以允许对象模型中存在一对多关系。

qyswt5oh

qyswt5oh1#

这里有两种方法可以做到这一点。出于懒惰,我把它们合并成一个例子。

@Serdeable
enum class Role {
    Admin, Manager;
}

@Serdeable
@MappedEntity
data class UserRole(
    @field:Id
    @GeneratedValue
    var id: Long? = null,
    @Nullable
    @Relation(value = Relation.Kind.MANY_TO_ONE)
    val user: User?,
    val role: Role
)

@Serdeable
@MappedEntity
class User(

    @field:Id
    @field:GeneratedValue
    var id: Long? = null,

    val username: String,

    @MappedProperty(definition = "VARCHAR(30)[]", type = DataType.STRING_ARRAY)
    var roles: Set<Role>?,

    @Relation(value = Relation.Kind.ONE_TO_MANY, mappedBy = "user", cascade = [Cascade.ALL])
    var userRoles: Set<UserRole>?
)

@JdbcRepository(dialect = Dialect.POSTGRES)
@Join(value = "userRoles", type = Join.Type.LEFT_FETCH)
interface UserRepository : CrudRepository<User, Long> {
}
CREATE TYPE role_name AS ENUM ('Admin', 'Manager');

CREATE TABLE "user"
(
    id       SERIAL PRIMARY KEY,
    username VARCHAR(30) NOT NULL UNIQUE,
    roles VARCHAR(15)[]
);

CREATE TABLE "user_role"
(
    id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
    user_id INTEGER REFERENCES "user" (id),
    role role_name NOT NULL,
    CONSTRAINT user_role_uk UNIQUE (user_id, role)
);

相关问题