출처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(16) NOT NULL,
`Account` VARCHAR(32) NULL DEFAULT NULL,
`Password` VARCHAR(64) NULL DEFAULT NULL,
PRIMARY KEY (`Id`),
UNIQUE INDEX `idx_user_account` (`Account`),
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
;
CREATE TABLE `table_user_properties` (
`UserId` BINARY(16) NOT NULL,
`Properties` INT(11) NOT 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;
}