我有一个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);

另外,还有一个用户表,但这并不重要,有了这个表,你就可以了解问题的全貌。
如您所见,有些列具有AUTO_INCREMENT属性,在@GeneratedValue(strategy = GenerationType.IDENTITY)类中将变为@Entity
OPERATIONrole_user具有复合主键,因为它们与其他表之间存在关系,所以我无法更改。由于复合PK,映射类必须有一个@EmbeddedId与相应的@Embeddable类。
问题是我需要一个@GeneratedValue在复合PK的“本机”部分,例如:OPERATION.id_operation必须有@GeneratedValue并且OPERATION.id_menu是从MENU.id_menu, butJPAdoes not support@GeneratedValuein@embeddeddid`传播的。我解释得对吗?
我尝试使用NetBeans的“suggestion”of the Entity classes from DataBase选项,但为具有简单列标识符(如@GeneratedValue)的表生成MENU注释,而不是为复合表生成OPERATION注释(如)。
所以问题是我该如何绘制地图?。更改数据库的结构不是一个选项,而是由于业务需求而这样做的。
感谢任何帮助或指导。提前非常感谢。

最佳答案

您的JPA@Id不需要匹配数据库PK列。只要它是唯一的,那么这就是最重要的,因为关联的列是一个自动递增的列,那么情况就是这样。
https://en.wikibooks.org/wiki/Java_Persistence/Identity_and_Sequencing
JPA Id并不总是必须与数据库表primary匹配
键约束,也不需要主键或唯一约束。
因此,虽然关联表的主键可以配置为PRIMARY KEY (id_operation, id_menu),但看起来,id_operation通过自动递增,可以单独作为主键,因此操作可以映射如下:

@Entity
public class Operation{

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

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

如果您创建了相关的IDClass,那么可以如下映射OperationRole。有关此场景的示例以及ID类的look方式,请参见:
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;
}

09-08 07:37