Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
401 views
in Technique[技术] by (71.8m points)

java - @EmbeddedId with @GeneratedValue in @Embeddable

I have a MySQL DB with the following structure (excerpt):

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);

Also, there's a USER table but it's not important, with these you can have the full picture of the problem.

As you can see, some columns has AUTO_INCREMENT property which will become @GeneratedValue(strategy = GenerationType.IDENTITY) in the @Entity classes.

OPERATION and role_user has composite primary keys because of the relation they have with the other tables, so I can't change that. Because of the composite PK, the mapped classes must have an @EmbeddedId with the corresponding @Embeddable class.

The problem is that I need a @GeneratedValue in the "native" part of the composite PK, e.g.: OPERATION.id_operation must have @GeneratedValue and OPERATION.id_menu is propagated from MENU.id_menu, butJPAdoes not support@GeneratedValuein@EmbeddedId`. Am I explaining correctly the situation?

I tried with the NetBeans's "suggestion" of the Entity classes from DataBase option but generates the @GeneratedValue annotation for the tables with simple column's identifier (like MENU) but not for the composite's one (like OPERATION).

So the question is how can I do the mapping?. Changing the structure of the DB is not an option, it's made that way because of the business requirements.

Any help or guide is appreciated. Thank you so much in advance.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Your JPA @Id does not need to match the database PK column(s). So long as it is unique then that is all that matters and as the associated column is an auto-increment column then this will be the case.

From 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.

So, while the PK for the associated table may be configured as PRIMARY KEY (id_operation, id_menu) it would seem, id_operation, through being auto-increment, could stand alone as a PK and therefore Operation can be mapped as below:

@Entity
public class Operation{

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

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

If you create the relevant IDClass then OperationRole can be mapped as below. For an example of this scenario and how the ID class would loook see:

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;
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...