我有一个具有以下结构的 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_INCRMENT
属性,该属性将在 @Entity
中变为 @GenerateValue(strategy = GenerationType.IDENTITY)
类。
OPERATION
和 role_user
由于它们与其他表的关系而具有复合主键,因此我无法更改它。由于复合 PK
,映射的类必须具有 @EmbeddedId
以及相应的 @Embeddable
类。
问题是我需要在复合PK
的“native”部分中使用@GenerateValue
,例如:OPERATION .id_operation
必须具有 @GenerateValue
且 OPERATION.id_menu
是从 MENU.id_menu 传播的,但
JPA不支持
@GenerateValue在
@EmbeddedId`中。我是否正确地解释了情况?
我尝试使用 NetBeans 的“来自 DataBase 的实体类”选项的“建议”,但使用简单的方法为表生成了 @GenerateValue
注释列的标识符(如 MENU
),但不是复合的标识符(如 OPERATION
)。
所以问题是我该如何进行映射?。更改数据库的结构不是一种选择,而是由于业务需求而这样做的。
感谢任何帮助或指导。提前非常感谢您。
最佳答案
您的 JPA @Id
不需要与数据库 PK 列匹配。只要它是唯一的,那么这就是最重要的,并且由于关联的列是自动增量列,那么情况就是如此。
来自https://en.wikibooks.org/wiki/Java_Persistence/Identity_and_Sequencing :
The JPA Id does not always have to match the database table primary key constraint, nor is a primary key or a unique constraint required.
因此,虽然关联表的 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 类的外观,请参见:
@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;
}
关于java - @EmbeddedId 和 @Embeddable 中的 @GenerateValue,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37448621/