출처1 : https://discourse.hibernate.org/t/hibernate-throws-org-hibernate-id-identifiergenerationexception-attempted-to-assign-id-from-null-one-to-one-property/1777/9

출처2 : https://kwonnam.pe.kr/wiki/java/jpa/one-to-one




개발환경 : spring boot 2.0.3.RELEASE / hibernate 5.2.17.Final / mariadb 10.x





아래와 같은 1:1 관계일 경우 하이버네이트 설정 방법


CREATE TABLE `table_user` (
    `Id` BINARY(16NOT NULL,
    `Account` VARCHAR(32NULL DEFAULT NULL,
    `Password` VARCHAR(64NULL DEFAULT NULL,
    PRIMARY KEY (`Id`),
    UNIQUE INDEX `idx_user_account` (`Account`),
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
;

CREATE TABLE `table_user_properties` (
    `UserId` BINARY(16NOT NULL,
    `Properties` INT(11NOT NULL,
    PRIMARY KEY (`UserId`),
    CONSTRAINT `fk_table_user_properties_table_user_id` 
        FOREIGN KEY (`UserId`REFERENCES `table_user` (`Id`
        ON UPDATE CASCADE ON DELETE CASCADE
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
;





UserProperties 를 저장할 때 setUser와 setUserProperties를 사용하여 양쪽에 맵핑을 해준다 하더라도 키가 없다면서 안되더라.

아마도 hibernate 5.2.13 버전까지는 되고 5.2.14 버전부터 지원하지 않는 것 같다.(버전을 낮추지 않아서 해보진 않았다.)

결론적으로는 양쪽에 맵핑을 해주지 말고 UserProperties에 대해서 서비스를 별도로 만든 후 해당 서비스로 데이터를 조작하여야 한다



@Entity
@Getter
@Setter
@Table(name = "table_user")
public class User implements Serializable {

    private static final long serialVersionUID = 111111111111111111L;

    @Id
    @Column(columnDefinition = "BINARY(16)", name = "Id")
    @GenericGenerator(name = "customUuid"
        strategy = "com.motolies.model.util.CustomUUIDGenerator")
    @GeneratedValue(generator = "customUuid")
    private byte[] id;

    @Column(name = "Account", length = 32, unique = true)
    @NotNull
    private String username;

    @JsonIgnore
    @Column(name = "Password", length = 64)
    @NotNull
    private String password;

    @JsonManagedReference
    @OneToOne(mappedBy = "user", targetEntity = UserProperties.class, fetch = FetchType.LAZY)
    @PrimaryKeyJoinColumn
    @org.hibernate.annotations.Cascade({ org.hibernate.annotations.CascadeType.SAVE_UPDATE
        , org.hibernate.annotations.CascadeType.LOCK })
    private UserProperties userProperties;

    public UserProperties getUserProperties() {
        // 1대 1 관계이므로, 항상 데이터가 있다고 가정하기에 null인 경우 만들어서 준다
        if (this.userProperties != null)
            return this.userProperties;
        else
            return new UserProperties(this);
    }

}


@Entity
@Getter
@Setter
@Table(name = "table_user_properties")
@NoArgsConstructor
public class UserProperties implements Serializable {

    private static final long serialVersionUID = 111111111111111111L;

    public UserProperties(User user) {
        this.user = user;
    }
    
    @Id
    @GeneratedValue(generator = "gen")
    @GenericGenerator(name = "gen", strategy = "foreign"
        , parameters = @Parameter(name = "property", value = "user"))
    @Column(columnDefinition = "BINARY(16)", name = "UserId")
    private byte[] userId;

    @JsonBackReference
    @OneToOne(fetch = FetchType.LAZY)
    @PrimaryKeyJoinColumn(name = "UserId", referencedColumnName = "Id")
    private User user;

}









Posted by motolies

댓글을 달아 주세요