Spring Boot ile Çoklu İlişkili Tablolarda İlişki Tablosuna Kayıt Ekleme İşlemi

Gamze Kaya
turkcell
Published in
3 min readDec 20, 2023

Spring Boot, Java tabanlı web uygulamalarını hızlı bir şekilde geliştirmek için tasarlanmış ve veritabanı işlemlerini kolaylaştıran açık kaynaklı bir framework’tür. Bu makalede, çoklu ilişkili tablolar içeren bir projede Spring Boot kullanarak ilişki tablosuna bir kayıt eklemeyi ele alacağız.

1. Proje Ayarları

Öncelikle, bir Spring Boot projesinin gerekli bağımlılıklara sahip olduğunu varsayarak işlemleri gerçekleştiriyoruz. Bu bağımlılıklar arasında veritabanı işlemlerini yöneten Spring Data, JPA ve ilişki yönetimini sağlayan Hibernate bulunmalıdır.

<dependencies>
<!-- Spring Boot Starter Web (Opsiyonel, Spring Boot uygulamaları için web desteği sağlar) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- Spring Data JPA -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

<!-- Hibernate JPA provider -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
</dependency>
</dependencies>

İlk adım olarak, çoklu ilişkilere sahip iki tabloyu entity olarak eklememiz gerekiyor. Bu ekleme işleminde, ilişki tablosu üzerinde etkili olan entity belirlenmeli ve yönetim bu entity üzerinden sağlanmalıdır.

2. Entity Tanımları

Örneğin, bir öğrencinin ders listesi ve bu dersi alan öğrencileri inceleyecek olursak, bir öğrencinin birden çok dersi olabilir veya bir dersin birden çok öğrencisi olabilir. Ayrıca her öğrenciye bir ders bir kez atanabilir. Bu düşünce ile tanımlamaların yapıldığını varsayabiliriz. “T_STUDENT” öğrenci bilgilerinin tutulduğu ilk ana tablodur. İlişki tablosu aralarında ilişki olan iki tabloyu birbirine bağlarken bu ana tablolardan yalnızca biri tarafından yönetilebilir olarak tanımlanmalıdır. “T_STUDENT” tablosu yetkili tablo olarak belirtilmiş ve tanımlamalar ona göre yapılmıştır.

@Table(name = "T_STUDENT")
@Data
public class Student {
private String Id;
private String firstName;
private String lastName;

@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinTable(name = "T_STUDENT_LESSON",
joinColumns = {@JoinColumn(name = "STUDENT_ID", referencedColumnName = "ID")},
inverseJoinColumns = {@JoinColumn(name = "LESSON_ID", referencedColumnName = "ID")})
private Set<Lesson> lessons = Sets.newHashSet();

}

Anatasyonları İnceleyelim;

  1. Yukarıdaki kod parçasında, @ManyToMany anotasyonu kullanılarak ilişki türü belirtilmiştir. fetch özelliği, ilişki verilerinin alınma stratejisini belirtir ve FetchType.LAZY ile belirtilmiştir, yani veriler yalnızca çağrıldığında alınacaktır. cascade özelliği ise ilişkili nesneler üzerinde hangi işlemlerin yürütüleceğini belirtir; burada CascadeType.ALL ile belirtilmiştir, bu da tüm işlemleri (ekleme, güncelleme, silme) kapsar.
  2. @JoinTable: Bu kısım, ilişkinin yönetildiği birleştirme tablosunu belirtir. name özelliği ile birleştirme tablosunun adı T_STUDENT_LESSON olarak belirlenmiştir.
  3. joinColumns ve inverseJoinColumns: Bu kısımlar, birleştirme tablosundaki ilgili sütunları belirler. joinColumns, öğrenci (Student) sınıfının anahtar sütununu (STUDENT_ID) ve bu sütunun referans aldığı alanı (referencedColumnName = “ID”) belirtir. inverseJoinColumns ise ders (Lesson) sınıfının anahtar sütununu (LESSON_ID) ve bu sütunun referans aldığı alanı (referencedColumnName = “ID”) belirtir.
  4. private Set<Lesson> lessons = Sets.newHashSet();: Bu kısım, ilişkiyi temsil eden Set koleksiyonunu tanımlar. Set kullanılması, her öğrencinin bir dersten yalnızca bir kez ders alabilmesini sağlar. (tekil ders — öğrenci ilişkisi).

T_LESSON ise ders bilgilerinin tutulduğu ikinci ana tablodur.

@Table(name = "T_LESSON")
@Data
public class Lesson {

@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "lessons")
private java.util.Set<Student> students = Sets.newHashSet();

}

Bu entity üzerinde tanımlanan mappedBy = “lessons”: Bu, ders (Lesson) sınıfında tanımlanan ilişkiyi belirtir. Yani, Lesson sınıfındaki “lessons” adlı özellik, bu tarafın (Student tarafı) yönettiği ilişkiyi temsil eder. Yani yönetici olarak belirtilen entity Student entitysi olarak işaretlenir.

İlişki tablosu olarak ise T_STUDENT_LESSON tablosu kurgulanmıştır. Tablo içerisinde Student id ve lesson id kolonları yer almaktadır.

3. Repository Tanımları

Kayıt işlemi yapabilmek için JPA repositoryleri oluşturmak gerekir. JPA repository’leri, veritabanı ile etkileşimde bulunmayı sağlayan Spring Data JPA tarafından sağlanan bir özelliktir.

Student Repository ;

@Repository
public interface StudentRepository extends JpaRepository<Student, Long>
{
Student findStudentById(Long studentId);
}

Lesson Repository ;

@Repository
public interface LessonRepository extends JpaRepository<Lesson, Long>
{
Student findLessonById(Long lessonId);
}

Bu repositorylerdeki find methodları sınıfın kendi türünden nesneleri arayıp bularak nesneyi döndürür.

4. Servis katmanı

Servis katmanı, genellikle iş kurallarını uygulayan controller ve repository arasında bağ kuran, veri manipülasyonunu gerçekleştiren ve kontrol katmanından gelen talepleri işleyen bir katmandır.

T_STUDENT_LESSON tablosuna kayıt ekleyebilmek için aşağıdaki kod parçacığı kullanılabilir.

@Override
@Transactional
public String saveOrUpdateStudentLesson(StudentLessonRequestDTO requestDTO) {
Student student = studentRepository.findStudentById(requestDTO.getStudentId());
checkNotNull(student, "Öğrenci bulunamadı!");

Lesson lesson = lessonRepository.findLessonById(requestDTO.getLessonId());
checkNotNull(lesson, "Ders bulunamadı!");

student.getLessons().add(lesson);

try {
studentRepository.saveAndFlush(student);
return student.getStudentNumber();

} catch (Exception e) {
throw new BusinessException("Öğrenci dersi veritabanına kaydedilirken hata oluştu: " + e.getMessage(),
ReturnType.FAILURE);
}
}

Bu adımlar, Spring Boot kullanarak çoklu ilişkili tablolarda ilişki tablosuna kayıt eklemek için genel bir rehberdir. Ancak, projenin gereksinimlerine ve karmaşıklığına bağlı olarak daha fazla özellik eklemek veya güvenlik önlemleri eklemek gerekebilir.

--

--