Bu çok yaygın bir soru, bu yüzden bu cevap blogumda yazdığım bu makaleye dayanıyor .
Bire birçok
Bir-çok tablo ilişkisi aşağıdaki gibi görünür:
İlişkisel veritabanı sisteminde, bire çok tablo ilişkisi , alt tablodaki üst tablo satırına Foreign Key
başvuruda bulunan sütunu temel alan iki tabloyu birbirine bağlar Primary Key
.
Yukarıdaki tablo diyagramda, post_id
sütun post_comment
tablo bir sahiptir Foreign Key
ilişki post
tablosu id Primary Key
sütun:
ALTER TABLE
post_comment
ADD CONSTRAINT
fk_post_comment_post_id
FOREIGN KEY (post_id) REFERENCES post
@ManyToOne ek açıklaması
Birden çok tablo ilişkisini eşlemenin en iyi yolu @ManyToOne
ek açıklamayı kullanmaktır .
Bizim durumumuzda, alt varlık, ek açıklamayı kullanarak Yabancı Anahtar sütununu PostComment
eşler :post_id
@ManyToOne
@Entity(name = "PostComment")
@Table(name = "post_comment")
public class PostComment {
@Id
@GeneratedValue
private Long id;
private String review;
@ManyToOne(fetch = FetchType.LAZY)
private Post post;
}
JPA @OneToMany
ek açıklamasını kullanma
@OneToMany
Ek açıklama kullanma seçeneğiniz olması , bunun her bir-çok veritabanı ilişkisi için varsayılan seçenek olması gerektiği anlamına gelmez . Koleksiyonlarla ilgili sorun, bunları yalnızca alt kayıtların sayısı oldukça sınırlı olduğunda kullanabilmemizdir.
Bir @OneToMany
ilişkilendirmeyi eşlemenin en iyi yolu, @ManyToOne
tüm varlık durumu değişikliklerini yaymak için tarafa güvenmektir :
@Entity(name = "Post")
@Table(name = "post")
public class Post {
@Id
@GeneratedValue
private Long id;
private String title;
@OneToMany(
mappedBy = "post",
cascade = CascadeType.ALL,
orphanRemoval = true
)
private List<PostComment> comments = new ArrayList<>();
//Constructors, getters and setters removed for brevity
public void addComment(PostComment comment) {
comments.add(comment);
comment.setPost(this);
}
public void removeComment(PostComment comment) {
comments.remove(comment);
comment.setPost(null);
}
}
Ana varlık, Post
iki yönlü ilişkinin her iki tarafını senkronize etmek için kullanılan iki faydalı yöntem (örneğin addComment
ve removeComment
) içerir. Her zaman aksi takdirde riske, siz iki yönlü dernek ile çalışıyorsanız her bu yöntemleri sağlamalıdır çok ince devlet yayılma sorunları .
Tek yönlü @OneToMany
ilişkiden, kullanımdan @ManyToOne
veya çift yönlü @OneToMany
ilişkiden daha az verimli olduğundan kaçınılmalıdır .
@OneToMany
JPA ve Hazırda Bekletme ile ilişkiyi eşleştirmenin en iyi yolu hakkında daha fazla bilgi için bu makaleye göz atın .
Bire bir
Bire bir tablo ilişkisi aşağıdaki gibidir:
İlişkisel veritabanı sisteminde, bire bir tablo ilişkisi , alt tablodaki ana tablo satırına Primary Key
da Foreign Key
gönderme yapan bir sütuna dayalı olarak iki tabloyu birbirine bağlar Primary Key
.
Bu nedenle, alt tablonun Primary Key
ana tabloyla paylaştığını söyleyebiliriz .
Yukarıdaki tablo diyagramda, id
sütun post_details
tablo da var Foreign Key
olan ilişkiyi post
tablo id
Primary Key
sütun:
ALTER TABLE
post_details
ADD CONSTRAINT
fk_post_details_id
FOREIGN KEY (id) REFERENCES post
JPA kullanarak @OneToOne
birlikte @MapsId
ek açıklamalar
Bir @OneToOne
ilişkiyi eşlemenin en iyi yolu kullanmaktır @MapsId
. Bu şekilde, varlık tanımlayıcısını PostDetails
kullanarak varlığı her zaman getirebileceğiniz için çift yönlü bir ilişkilendirmeye bile ihtiyacınız yoktur Post
.
Eşleme şöyle görünür:
[code language = "java"] @Entity (name = "PostDetails") @Table (name = "post_details") genel sınıf PostDetails {
@Id
private Long id;
@Column(name = "created_on")
private Date createdOn;
@Column(name = "created_by")
private String createdBy;
@OneToOne(fetch = FetchType.LAZY)
@MapsId
@JoinColumn(name = "id")
private Post post;
public PostDetails() {}
public PostDetails(String createdBy) {
createdOn = new Date();
this.createdBy = createdBy;
}
//Getters and setters omitted for brevity
} [/ kod]
Bu şekilde, id
tesis hem Ana Anahtar hem de Yabancı Anahtar olarak hizmet vermektedir. Tanımlayıcı ilişkilendirmenin tanımlayıcısıyla doldurulduğundan @Id
sütunun artık bir @GeneratedValue
ek açıklama kullanmadığını fark edeceksiniz post
.
@OneToOne
JPA ve Hazırda Bekletme ile ilişkiyi eşleştirmenin en iyi yolu hakkında daha fazla bilgi için bu makaleye göz atın .
Birçok çoğa
Çoktan çoğa tablo ilişkisi şöyle görünür:
İlişkisel veritabanı sisteminde, çoktan çoğa tablo ilişkisi , iki üst tabloyu, iki üst tablodaki Foreign Key
sütunlara başvuran iki sütun içeren bir alt tablo aracılığıyla bağlar Primary Key
.
Yukarıdaki tablo diyagramda, post_id
sütun post_tag
tablo da var Foreign Key
olan ilişkiyi post
tablo id Primary Key
sütun:
ALTER TABLE
post_tag
ADD CONSTRAINT
fk_post_tag_post_id
FOREIGN KEY (post_id) REFERENCES post
Ve, tag_id
sütun post_tag
tabloda bir sahip Foreign Key
ile ilişki tag
tablo id Primary Key
sütununun:
ALTER TABLE
post_tag
ADD CONSTRAINT
fk_post_tag_tag_id
FOREIGN KEY (tag_id) REFERENCES tag
JPA @ManyToMany
eşlemesini kullanma
many-to-many
JPA ve Hazırda Bekletme ile tablo ilişkisini şu şekilde eşleyebilirsiniz :
@Entity(name = "Post")
@Table(name = "post")
public class Post {
@Id
@GeneratedValue
private Long id;
private String title;
@ManyToMany(cascade = {
CascadeType.PERSIST,
CascadeType.MERGE
})
@JoinTable(name = "post_tag",
joinColumns = @JoinColumn(name = "post_id"),
inverseJoinColumns = @JoinColumn(name = "tag_id")
)
private Set<Tag> tags = new HashSet<>();
//Getters and setters ommitted for brevity
public void addTag(Tag tag) {
tags.add(tag);
tag.getPosts().add(this);
}
public void removeTag(Tag tag) {
tags.remove(tag);
tag.getPosts().remove(this);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Post)) return false;
return id != null && id.equals(((Post) o).getId());
}
@Override
public int hashCode() {
return 31;
}
}
@Entity(name = "Tag")
@Table(name = "tag")
public class Tag {
@Id
@GeneratedValue
private Long id;
@NaturalId
private String name;
@ManyToMany(mappedBy = "tags")
private Set<Post> posts = new HashSet<>();
//Getters and setters ommitted for brevity
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Tag tag = (Tag) o;
return Objects.equals(name, tag.name);
}
@Override
public int hashCode() {
return Objects.hash(name);
}
}
- Varlıktaki
tags
ilişkilendirme Post
yalnızca PERSIST
ve MERGE
basamaklı türleri tanımlar . Bu makalede açıklandığı gibi , REMOVE
varlık durumu geçişi , bir @ManyToMany
JPA ilişkilendirmesi için hiçbir anlam ifade etmemektedir, çünkü birliğin her iki tarafını da silecek bir zincir silinmesini tetikleyebilir.
- Bu makalede açıklandığı gibi , çift yönlü ilişkilendirmeler kullanırsanız, ilişkilendirmenin her iki tarafının da eşit olduğundan emin olmak için ekleme / kaldırma yardımcı programı yöntemleri zorunludur.
Post
Herhangi benzersiz iş anahtarını yoksun beri varlık eşitlik için varlık tanımlayıcı kullanır. Bu makalede açıklandığı gibi, tüm varlık durumu geçişlerinde tutarlı kaldığından emin olarak varlık tanımlayıcısını eşitlik için kullanabilirsiniz .
Tag
Varlık hazırda özgü işaretlenir benzersiz bir iş anahtarı vardır @NaturalId
açıklama. Böyle bir durumda, benzersiz iş anahtarı eşitlik kontrolleri için en iyi adaydır .
mappedBy
Öznitelik posts
içinde dernek Tag
, bu iki yönlü bir ilişki içinde, varlık işaretleri Post
varlık ilişki var. Bu, yalnızca bir tarafın bir ilişkiye sahip olabileceği ve değişikliklerin veritabanına yalnızca bu belirli taraftan yayıldığı için gereklidir.
Set
Kullanarak olarak tercih edilir List
olan @ManyToMany
daha az verimlidir.
@ManyToMany
JPA ve Hazırda Bekletme ile ilişkiyi eşleştirmenin en iyi yolu hakkında daha fazla bilgi için bu makaleye göz atın .