Micronaut Data JDBC:如何用枚举映射单向一对多关系?
Micronaut Data 实现用户-角色单向一对多关系映射
需求说明
通过Micronaut Data注解,将给定的Kotlin对象模型(User包含Set<Role>)映射为单向一对多关系,可调整数据库模型以适配对象模型。
给定对象模型
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, // 需要映射的角色集合 var roles: Set<Role>? = null )
方案一:基于原多对多数据库模型适配
修改后的数据库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 UNIQUE ); CREATE TABLE "user_role" ( id SERIAL PRIMARY KEY, user_id INTEGER NOT NULL REFERENCES "user" (id), role_id INTEGER NOT NULL REFERENCES "role" (id), CONSTRAINT user_role_unique UNIQUE (user_id, role_id) ); INSERT INTO "role" (id, name) VALUES (1, 'Admin'), (2, 'Manager');
映射后的User实体代码
通过Micronaut Data的@Relation和@JoinTable注解实现单向一对多映射:
import io.micronaut.data.annotation.* import io.micronaut.serde.annotation.Serdeable import jakarta.persistence.Enumerated import jakarta.persistence.EnumType @Serdeable @MappedEntity data class User( @field:Id @field:GeneratedValue var id: Long? = null, val username: String, // 单向一对多映射配置 @field:Relation(Relation.Kind.ONE_TO_MANY) @field:JoinTable( name = "user_role", joinColumns = [JoinColumn(name = "user_id")], inverseJoinColumns = [JoinColumn(name = "role_id", referencedColumnName = "id")] ) @field:Enumerated(EnumType.STRING) var roles: Set<Role>? = null )
注解说明:
@Relation(Relation.Kind.ONE_TO_MANY):声明该字段为单向一对多关系@JoinTable:指定关联中间表的名称及字段映射,joinColumns关联当前实体(User)的主键,inverseJoinColumns关联Role表的主键@Enumerated(EnumType.STRING):将枚举类型映射为数据库中的字符串值,与role表的name字段对应
方案二:使用PostgreSQL枚举类型简化模型
利用PostgreSQL原生枚举类型,省去独立的role表,直接在关联表中存储枚举值,更贴合对象模型:
修改后的数据库DDL
CREATE TABLE "user" ( id SERIAL PRIMARY KEY, username VARCHAR(30) NOT NULL UNIQUE ); -- 创建与Kotlin枚举完全对应的PostgreSQL枚举类型 CREATE TYPE role_name AS ENUM ('Admin', 'Manager'); CREATE TABLE "user_role" ( id SERIAL PRIMARY KEY, user_id INTEGER NOT NULL REFERENCES "user" (id), role role_name NOT NULL, CONSTRAINT user_role_unique UNIQUE (user_id, role) );
映射后的User实体代码
import io.micronaut.data.annotation.* import io.micronaut.serde.annotation.Serdeable import jakarta.persistence.Enumerated import jakarta.persistence.EnumType @Serdeable @MappedEntity data class User( @field:Id @field:GeneratedValue var id: Long? = null, val username: String, // 单向一对多映射配置 @field:Relation(Relation.Kind.ONE_TO_MANY) @field:JoinColumn(name = "user_id") @field:Column(name = "role") @field:Enumerated(EnumType.STRING) var roles: Set<Role>? = null )
注解说明:
@Relation(Relation.Kind.ONE_TO_MANY):声明单向一对多关系@JoinColumn(name = "user_id"):指定关联表中对应用户主键的外键字段@Column(name = "role"):指定关联表中存储枚举值的字段@Enumerated(EnumType.STRING):确保枚举与PostgreSQL枚举类型的字符串值匹配
额外配置
为让Micronaut Data正确识别PostgreSQL枚举类型,需在application.yml中添加方言配置:
jpa: properties: hibernate: dialect: org.hibernate.dialect.PostgreSQLDialect
内容的提问来源于stack exchange,提问作者Alexandre V.
相关产品推荐
相关产品推荐

