Hangi durumda JPA @JoinTableek açıklamasını kullanıyorsunuz?
Hangi durumda JPA @JoinTableek açıklamasını kullanıyorsunuz?
Yanıtlar:
EDIT 2017-04-29 : Bazı yorumcular tarafından işaret edildiği gibi, JoinTableörnek mappedByek açıklama özelliğine ihtiyaç duymaz . Aslında, Hibernate'in son sürümleri aşağıdaki hatayı yazarak başlatılmayı reddeder:
org.hibernate.AnnotationException:
Associations marked as mappedBy must not define database mappings
like @JoinTable or @JoinColumn
Şu adda bir varlığınız olduğunu varsayalım: Project ve başka bir varlığınız olduğunu Taskve her projenin birçok görevi olabileceğini .
Bu senaryo için veritabanı şemasını iki şekilde tasarlayabilirsiniz.
İlk çözüm, adlı bir tablo Projectve adlı başka bir tablo oluşturmak ve Taskşu görev tablosuna bir yabancı anahtar sütunu eklemektir project_id:
Project Task
------- ----
id id
name name
project_id
Bu şekilde, görev tablosundaki her satır için projeyi belirlemek mümkün olacaktır. Bu yaklaşımı kullanırsanız, varlık sınıflarınızda bir birleştirme tablosuna ihtiyacınız olmaz:
@Entity
public class Project {
@OneToMany(mappedBy = "project")
private Collection<Task> tasks;
}
@Entity
public class Task {
@ManyToOne
private Project project;
}
Diğer çözüm, örneğin üçüncü bir tablo kullanmak Project_Tasksve bu tablodaki projeler ve görevler arasındaki ilişkiyi saklamaktır:
Project Task Project_Tasks
------- ---- -------------
id id project_id
name name task_id
Project_TasksTablo "Üyelik Tablosu" denir. Bu ikinci çözümü JPA'da uygulamak için aşağıdaki çözümü kullanmanız gerekir:@JoinTable ek açıklamayı . Örneğin, bire bir çok yönlü bir birliktelik uygulamak için varlıkları şöyle tanımlayabiliriz:
Project varlık:
@Entity
public class Project {
@Id
@GeneratedValue
private Long pid;
private String name;
@JoinTable
@OneToMany
private List<Task> tasks;
public Long getPid() {
return pid;
}
public void setPid(Long pid) {
this.pid = pid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Task> getTasks() {
return tasks;
}
public void setTasks(List<Task> tasks) {
this.tasks = tasks;
}
}
Task varlık:
@Entity
public class Task {
@Id
@GeneratedValue
private Long tid;
private String name;
public Long getTid() {
return tid;
}
public void setTid(Long tid) {
this.tid = tid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Bu, aşağıdaki veritabanı yapısını oluşturur:
@JoinTableEk açıklama da katılmak tablonun çeşitli yönlerini özelleştirmenizi sağlar. Örneğin, tasksmülke şu şekilde ek açıklama eklemiş olsaydık :
@JoinTable(
name = "MY_JT",
joinColumns = @JoinColumn(
name = "PROJ_ID",
referencedColumnName = "PID"
),
inverseJoinColumns = @JoinColumn(
name = "TASK_ID",
referencedColumnName = "TID"
)
)
@OneToMany
private List<Task> tasks;
Ortaya çıkan veritabanı:
Son olarak, çoktan çoğa ilişkilendirme için bir şema oluşturmak istiyorsanız, birleştirme tablosu kullanmak tek çözümdür.
@JoinTable/@JoinColumnAynı alana açıklama eklenebilir olduğuna inanıyorum mappedBy. Doğru örnek tutulması gerekir, böylece mappedByin Projectve hareket @JoinColumniçin Task.project (veya tam tersi ya da)
Project_Tasksihtiyacı nameiçinde Tasküç sütun haline gelir, sıra: project_id, task_id, task_name, nasıl bunu başarmak için?
Caused by: org.hibernate.AnnotationException: Associations marked as mappedBy must not define database mappings like @JoinTable or @JoinColumn:
@JoinTableBir Varlığın farklı ebeveynlerle çeşitli ebeveyn / çocuk ilişkilerinde çocuk olabileceği durumlarda da kullanmak daha temizdir . Behrang örneğini takip etmek için, bir görevin Proje, Kişi, Departman, Çalışma ve Sürecin çocuğu olabileceğini hayal edin.
taskTablonun 5 nullableyabancı anahtar alanı olmalı mı ? Bence değil...
ManyToMany ilişkilendirmesini eşlemek için tek çözümdür: ilişkilendirmeyi eşlemek için iki varlık tablosu arasında bir birleştirme tablosuna ihtiyacınız vardır.
Ayrıca, birçok tarafın tablosuna yabancı bir anahtar eklemek istemediğinizde OneToMany (genellikle tek yönlü) dernekler için kullanılır ve böylece onu bir taraftan bağımsız tutar.
Açıklamalar ve örnekler için hazırda bekletme belgesinde @JoinTable öğesini arayın .
Çoktan çoğa ilişkiyi ele almanızı sağlar. Misal:
Table 1: post
post has following columns
____________________
| ID | DATE |
|_________|_________|
| | |
|_________|_________|
Table 2: user
user has the following columns:
____________________
| ID |NAME |
|_________|_________|
| | |
|_________|_________|
Birleştirme Tablosu aşağıdakileri kullanarak bir eşleme oluşturmanıza olanak tanır:
@JoinTable(
name="USER_POST",
joinColumns=@JoinColumn(name="USER_ID", referencedColumnName="ID"),
inverseJoinColumns=@JoinColumn(name="POST_ID", referencedColumnName="ID"))
bir tablo oluşturur:
____________________
| USER_ID| POST_ID |
|_________|_________|
| | |
|_________|_________|
@ManyToMany derneklerÇoğu zaman, @JoinTableçoktan çoğa bir tablo ilişkisinin eşlenmesini belirtmek için ek açıklama kullanmanız gerekir :
Yani, aşağıdaki veritabanı tablolarına sahip olduğunuzu varsayarsak:
Gelen Postvarlık, böyle bu ilişkiyi, harita olacaktır:
@ManyToMany(cascade = {
CascadeType.PERSIST,
CascadeType.MERGE
})
@JoinTable(
name = "post_tag",
joinColumns = @JoinColumn(name = "post_id"),
inverseJoinColumns = @JoinColumn(name = "tag_id")
)
private List<Tag> tags = new ArrayList<>();
@JoinTableEk açıklama yoluyla tablo adı belirtmek için kullanılır nameözniteliği, hem de yabancı anahtar sütununun olduğu referanslar posttablo (örneğin joinColumns) ve Yabancı anahtar sütun post_tagbağlantı tablosunun o referanslar Tagyoluyla varlık inverseJoinColumnsözelliğinde.
@ManyToManyEk açıklamanın basamaklı özniteliğinin olarak ayarlandığına dikkat edinPERSISTveMERGEyalnızcaREMOVEDELETE deyiminin,tagbizim durumumuzda,post_tagkayda değil , diğer üst kayıt için yayınlanacağı için basamaklı kötü bir fikir olduğu için . Bu konu hakkında daha fazla bilgi için bu makaleye göz atın .
@OneToManyilişkilerTek yönlü @OneToManydernekler,@JoinColumnEşleme bulunmayan bire çok değil, çoktan çoğa tablo ilişkileri gibi davranır.
Aşağıdaki varlık eşlemelerine sahip olduğunuzu varsayarsak:
@Entity(name = "Post")
@Table(name = "post")
public class Post {
@Id
@GeneratedValue
private Long id;
private String title;
@OneToMany(
cascade = CascadeType.ALL,
orphanRemoval = true
)
private List<PostComment> comments = new ArrayList<>();
//Constructors, getters and setters removed for brevity
}
@Entity(name = "PostComment")
@Table(name = "post_comment")
public class PostComment {
@Id
@GeneratedValue
private Long id;
private String review;
//Constructors, getters and setters removed for brevity
}
Hazırda Beklet, yukarıdaki varlık eşlemesi için aşağıdaki veritabanı şemasını alır:
Daha önce açıklandığı gibi, tek yönlü @OneToManyJPA eşlemesi çoktan çoğa bir ilişki gibi davranır.
Bağlantı tablosunu özelleştirmek için @JoinTableek açıklamayı da kullanabilirsiniz :
@OneToMany(
cascade = CascadeType.ALL,
orphanRemoval = true
)
@JoinTable(
name = "post_comment_ref",
joinColumns = @JoinColumn(name = "post_id"),
inverseJoinColumns = @JoinColumn(name = "post_comment_id")
)
private List<PostComment> comments = new ArrayList<>();
Ve şimdi, bağlantı tablosu çağrılacak post_comment_refve Yabancı Anahtar sütunları post_id, posttablo post_comment_idiçin ve post_commenttablo için olacak.
Tek yönlü
@OneToManyilişkilendirmeler verimli değildir, bu nedenle iki yönlü@OneToManyilişkilendirmeleri veya yalnızca@ManyToOnetarafı kullanmaktan daha iyi olursunuz . Bu konu hakkında daha fazla bilgi için bu makaleye göz atın .