@EmbeddedId 和 @Embeddable 中的 @GeneratedValue

Posted

技术标签:

【中文标题】@EmbeddedId 和 @Embeddable 中的 @GeneratedValue【英文标题】:@EmbeddedId with @GeneratedValue in @Embeddable 【发布时间】:2016-09-23 17:39:35 【问题描述】:

我有一个具有以下结构的 mysql 数据库(摘录):

CREATE TABLE MENU(
    id_menu    TINYINT      UNSIGNED    NOT NULL    AUTO_INCREMENT,
    name       VARCHAR(50)              NOT NULL,
    PRIMARY KEY (id_menu)
);

CREATE TABLE OPERATION(
    id_operation    SMALLINT        UNSIGNED    NOT NULL    AUTO_INCREMENT,
    id_menu         TINYINT         UNSIGNED    NOT NULL,
    operation       VARCHAR(50)                 NOT NULL,
    url             VARCHAR(100)                NOT NULL,
    PRIMARY KEY (id_operation, id_menu)
);

CREATE TABLE operation_role(
    id_operation    SMALLINT    UNSIGNED    NOT NULL,
    id_menu         TINYINT     UNSIGNED    NOT NULL,
    role            CHAR(15)                NOT NULL,
    id_user         BIGINT      UNSIGNED    NOT NULL,
   PRIMARY KEY (id_operation, id_menu, role, id_user)
);

CREATE TABLE role_user(
    role          CHAR(15)              NOT NULL
    id_user       BIGINT      UNSIGNED  NOT NULL,
    PRIMARY KEY (role, id_user)
);

-- RELATIONSHIPS

-- 
-- TABLE: OPERATION 
-- Meaning: a MENU has several OPERATION (One to Many relationship)
ALTER TABLE OPERACION ADD CONSTRAINT fk_menu_operacion 
    FOREIGN KEY (id_menu)
    REFERENCES MENU(id_menu);

-- 
-- TABLE: operation_rol 
-- This is the join table for the Many to Many relatioship OPERATION-role_user
ALTER TABLE operation_role ADD CONSTRAINT fk_operation_oprole 
    FOREIGN KEY (id_operation, id_menu)
    REFERENCES OPERATION(id_operation, id_menu);

ALTER TABLE operaciones_rol ADD CONSTRAINT fk_roles_operation 
    FOREIGN KEY (role, id_user)
    REFERENCES role_user(role, id_user);

-- 
-- TABLE: roles_usuario 
-- Meaning: a user can have several roles (One to Many)
ALTER TABLE roles_usuario ADD CONSTRAINT fk_usuario_roles 
    FOREIGN KEY (id_usuario)
    REFERENCES USUARIO(id_usuario);

此外,还有一个 USER 表,但它并不重要,通过这些您可以全面了解问题。

如您所见,某些列具有AUTO_INCREMENT 属性,该属性将在@Entity 类中变为@GeneratedValue(strategy = GenerationType.IDENTITY)

OPERATIONrole_user 具有复合主键,因为它们与其他表有关系,所以我无法更改。由于复合PK,映射类必须有一个@EmbeddedId 和对应的@Embeddable 类。

问题是我需要在复合 PK"native" 部分中添加一个 @GeneratedValue,例如:OPERATION.id_operation 必须有 @GeneratedValueOPERATION.id_menu 传播自MENU.id_menu, butJPAdoes not support@GeneratedValuein@EmbeddedId`。我是否正确解释了情况?

我尝试使用 NetBeans 的 "suggestion"Entity classes from DataBase 选项,但为具有简单列标识符的表生成 @GeneratedValue 注释(如 @987654339 @) 但不适用于组合的(如OPERATION)。

所以问题是如何进行映射?。更改数据库的结构不是一种选择,而是出于业务需求。

感谢任何帮助或指导。非常感谢您。

【问题讨论】:

【参考方案1】:

您的 JPA @Id 不需要匹配数据库 PK 列。只要它是唯一的,那么这就是最重要的,并且由于关联的列是一个自动递增的列,那么情况就是如此。

来自https://en.wikibooks.org/wiki/Java_Persistence/Identity_and_Sequencing:

JPA Id 并不总是必须与数据库表主表匹配 键约束,也不需要主键或唯一约束。

因此,虽然关联表的 PK 可以配置为 PRIMARY KEY (id_operation, id_menu),但 id_operation 通过自动递增,可以单独作为一个 PK,因此操作可以映射如下:

@Entity
public class Operation

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne
    @JoinColumn(name = "id_menu")
    private Menu menu;

如果您创建相关的 IDClass,则 OperationRole 可以映射如下。有关此场景的示例以及 ID 类的外观,请参见:

https://en.wikibooks.org/wiki/Java_Persistence/Identity_and_Sequencing#Example_JPA_2.0_ManyToOne_id_annotation

@Entity
@IdClass(OperationRolePk.class)
public class OperationRole

        @Id
        @ManyToOne
        @JoinColumn(name = "id_operation")
        private Operation operation;

        @Id
        @ManyToOne
        @JoinColumn(name = "id_menu")
        private Menu menu;

        @Id
        @ManyToOne
        @JoinColumn(name = "id_user")
        private User user;

【讨论】:

嗯,这让我安心了,谢谢。现在,如何将MENU.id_menu 的传播从MENU 表映射到OPERATION,然后再映射到operation_role?有了它,我会非常高兴 为 OperationRole 更新。不确定操作是否需要其他任何东西。只需设置相关的菜单。 好的,我会试一试,告诉你进展如何。感谢您的宝贵时间

以上是关于@EmbeddedId 和 @Embeddable 中的 @GeneratedValue的主要内容,如果未能解决你的问题,请参考以下文章

Embeddable 和 EmbeddedId 之间的 JPA 映射 @ManyToOne

为啥我的带有@EmbeddedId 的实体不能在其对应的@Embeddable 类中使用LocalDateTime?

使用@EmbeddedId进行映射时出现Eclipse错误

使用 @EmbeddedId 映射时出现 Eclipse 错误

hibernate注解

hibernate 两个外键作为主键(注解方式)