Husband (husband_id PK, name)
Wife (wife_id PK, name, husband_id FK UNIQUE)
業務規則:一個丈夫對應一個妻子,妻子表持有丈夫外鍵且唯一。
@Entity
@Table(name = "Husband")
public class Husband {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "husband_id")
private Long id;
private String name;
@OneToOne(mappedBy = "husband", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private Wife wife; // 可選:雙向導航
// getters/setters
}
@Entity
@Table(name = "Wife",
uniqueConstraints = @UniqueConstraint(columnNames = "husband_id")
)
public class Wife {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "wife_id")
private Long id;
private String name;
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "husband_id", nullable = false, unique = true)
private Husband husband;
// getters/setters
}
| 註解 | 作用 |
|---|---|
@OneToOne | 聲明一對一關聯 |
@JoinColumn(name="husband_id", unique=true) | 指定外鍵列名,unique=true 生成唯一約束 (DDL) |
mappedBy="husband" | 放在非持有方,表示由 Wife.husband 維護關聯 |
@UniqueConstraint(columnNames="husband_id") | 表級唯一約束,雙重保障 |
nullable=false | 外鍵非空,強制關聯 |
public class Husband {
// ...
public void setWife(Wife wife) {
if (wife == null) {
if (this.wife != null) this.wife.setHusband(null);
} else {
wife.setHusband(this);
}
this.wife = wife;
}
}
public class Wife {
// ...
public void setHusband(Husband husband) {
this.husband = husband;
}
}
統一由 Husband 端管理關聯,避免雙向同步混亂。
@JsonManagedReference / @JsonBackReference 或 @JsonIgnore。@Transactional 範圍或用 fetch = FetchType.EAGER (慎用)。@JoinColumn(name="husband_id", referencedColumnName="husband_id") 顯式指定。@MapsId + @OneToOne,不再需要 @JoinColumn。
CREATE TABLE Husband (
husband_id BIGINT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50)
);
CREATE TABLE Wife (
wife_id BIGINT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50),
husband_id BIGINT NOT NULL UNIQUE,
FOREIGN KEY (husband_id) REFERENCES Husband(husband_id)
);
掌握 @JoinColumn(unique=true) + mappedBy 雙向配置,即可優雅實現一對一唯一外鍵關聯。