Hibernate

Hibernate 4 – @OneToOne, @OneToMany, @JoinColumn, @SequenceGenerator

Merhaba arkadaşlar derslerimize devam ediyoruz.

İlişkilere bir önceki derste ufak bir giriş yapmıştık.  Bu dersimiz de yeni dipnotlar kullanarak ilişkilerimizi geliştireceğiz.

Bu örneğimizde maven tabanlı yeni bir proje acıyoruz ve gerekli dependecy’leri ekliyoruz. İlk dersimizde bahsetmistim nasıl ekleneceğini oradan bakabilirsiniz.

Peki bu dersimiz de yeni dipnotlar kullanacağız dedik. Nedir bunlar?

İlk olarak kullanacağımız annotation(dipnot) @OneToOne’nın kullanımını göreceğiz.

@OneToOne nedir?

Şöyle bir örnek verebiliriz.  Bu örneğimizde bir öğrencinin sadece bir adresi olduğu varsayıyoruz.

Student <-> Adress

Bir öğrencinin bir tane adresi var ve bir adresi de sadece bir öğrenciye verebiliyoruz. Yani ikinci bir öğrenci aynı adreste kalamaz, bizim örneğimizde.

 

Untitled

Resmimize baktığımızda her öğrencinin bir tane evi var ve aynı evde iki öğrenci kalamıyor.

Şimdi yeni bir proje oluşturmuştuk ve projemize iki tane sınıf ekleyelim. Biri Student, diğeri ise Adress olucak ve ikisini de @Entity tanımlayacağız.

 

İlk olarak Adress clasını tanımlıyoruz.

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "ADRESS")
public class Adress {

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	@Column(name = "ADRESS_ID")
	private int adressId;
	
	@Column(name = "STREET", length = 40)
	private String street;

	@Column(name = "CITY")
	private String city;
	
	@Column(name = "COUNTRY")
	private String country;
	
	public Adress() {
		// TODO Auto-generated constructor stub
	}

	public Adress(String street, String city, String country) {
		this.street = street;
		this.city = city;
		this.country = country;
	}

	@Override
	public String toString() {
		return "Adress [adressId=" + adressId + ", street=" + street + ", city=" + city + ", country=" + country + "]";
	}

	public int getAdressId() {
		return adressId;
	}

	public void setAdressId(int adressId) {
		this.adressId = adressId;
	}

	public String getStreet() {
		return street;
	}

	public void setStreet(String street) {
		this.street = street;
	}

	public String getCity() {
		return city;
	}

	public void setCity(String city) {
		this.city = city;
	}

	public String getCountry() {
		return country;
	}

	public void setCountry(String country) {
		this.country = country;
	}
	
}

Burada Adress clasımızı @Entity olarak belirttik ve bir class’ın @Entity olabilmesi için iki şartımız vardı.

@Entity ve @Id dipnotunu kullanmak zorundaydık.

Bu örneğimiz de @Column içinde yeni bir özellik tanımladık. ‘length = 40’ bu bizim tablomuzun o sütunu için kaç karakterlik bir alana sahip olduğunu belirtiyoruz. Varsayılan değer 255 tir.

 

Şimdi sıradaki @Entity’miz olan Student sınıfımıza bakıyoruz.

 

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToOne;

@Entity
public class Student {

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	@Column(name = "STUDENT_ID")
	private int studentId;
	
	@Column(name = "NAME", unique = false)
	private String name;
	
	@Column(name = "SURNAME")
	private String surname;
	
	@OneToOne
	private Adress adress;
	
	public Student() {
		// TODO Auto-generated constructor stub
	}

	public Student(String name, String surname, Adress adress) {
		this.name = name;
		this.surname = surname;
		this.adress = adress;
	}

	@Override
	public String toString() {
		return "Student [studentId=" + studentId + ", name=" + name + ", surname=" + surname + ", adress=" + adress
				+ "]";
	}

	//Set get metotlarını tanımlayınız.

	}

Burada Adres nesnesinin üzerinde @OneToOne dipnotunu kullandık.  Bu sayede programımızı çalıştırdığımızda Student tablomuza adress_id adında bir foreign key bilgisi eklenecek.

Burada birde @Column dipnotu içinde ‘unique = false’ property tablosu tanımladık. Bu demek oluyor ki o sütunda aynı isimden birden fazla tanımlanabilir. Biz onu true yapsaydık aynı isimden o sütunda tanımlanamazdı. Ara ara böyle ufak detaylar vereceğim.

 

hibernate.cfg.xml dosyamızda oluşturduğumuz @Entity’leri bildiriyorduk.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
                                         "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
 <session-factory name="">
  
  <property name="hibernate.connection.driver_class">org.postgresql.Driver</property>
  
  <property name="hibernate.connection.url">jdbc:postgresql://127.0.0.1:5432/Hibernate</property>
  
  <property name="hibernate.connection.username">postgres</property>
  <property name="hibernate.connection.password">123456</property>
  
  <property name="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</property>
 
  <property name="hibernate.hbm2ddl.auto">create</property>
  <property name="hibernate.show_sql">true</property>
  
  <mapping class="Student"/>
  <mapping class="Adress"/>
  
 </session-factory>
</hibernate-configuration>

 

Daha sonra main metodumuzun bulunduğu sınıfa gelelim.

Burada her zamanki gibi SessionFactory ve Session nesneleri oluşturup Session nesnesiyle de tablolarımızı oluşturup verileri ekliyorduk.

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class Test {

	public static void main(String[] args) {
		
		Adress adress1 = new Adress("Cumhuriyet cad.", "Ankara", "Turkiye");
		Adress adress2 = new Adress("Çankaya cad", "Ankara", "Turkiye");
		Adress adress3 = new Adress("Kazım Karabekir cad.", "Ankara", "Turkiye");
		
		Student student1 = new Student("Ferhat", "Aykan", adress3);
		Student student2 = new Student("Enes", "Çınar", adress1);
		Student student3 = new Student("Uğur", "Baş", adress2);
		
		
		SessionFactory sessionFactory = new Configuration().configure("hibernate.cfg.xml").buildSessionFactory();
		Session session = sessionFactory.openSession();
		
		session.save(student1);
		session.save(student2);
		session.save(student3);
		session.save(adress1);
		session.save(adress2);
		session.save(adress3);
		
		
		session.beginTransaction().commit();
		session.close();
		
	}
}

Burada oluşturduğumuz bütün @Entity nesnelerini save ediyoruz. Programımızı çalıştırdığımızda ise karşımıza şöyle bir görüntü çıkacaktır.

 

2.RESİM

 

İki tane tablo oluştuğunu görmekteyiz.

Adres tablomuzun primary key’i Student tablosuna foreign key olarak eklendiğini ve Foreign key’in bulunduğu sütunun adı ‘adress_adress_id’ şeklind olduğunu görmekteyiz. Bu örneğe dikkatlice bakarsak iki tane tablomuz ve her tablonun kendine ait primary key’i mevcut ama biri 1 den başlarken diğeri 4 ten başlamaktadır. Biz bu örneğimizde bir tane sequence oluşturup ve her tablomuzda ki primary key için aynı sequence kullandığımızdan veriler eklendikçe otomatik bir şekilde sayı değeri artmaktadır.

 

Biz aynı örneğimizde ufak değişikler yaparak daha güzel gözükmesini sağlayacağız.

İlk olarak her tablo için bir tane sequnce oluşturacağız ve kaçtan başlatacağımızı biz belirteceğiz ve her veri eklendiğinde tablomuzda ki primary key olarak tanımladığımız ‘id’ değeri otomatik bir şekilde artacaktır.

Bir diğer değişikliğimiz ise Student tablosuna Adress tablosundan gelen foreign key’e sahip sütunun adını değiştireceğiz.

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;

@Entity
@Table(name = "ADRESS")
public class Adress {

	@Id
	@SequenceGenerator(name = "ADRESS_SEQUENCE_GENERATOR", sequenceName = "ADRESS_SEQUENCE", initialValue = 10)
	@GeneratedValue(generator = "ADRESS_SEQUENCE_GENERATOR")
	@Column(name = "ADRESS_ID")
	private int adressId;
	
	@Column(name = "STREET", length = 40)
	private String street;

	@Column(name = "CITY")
	private String city;
	
	@Column(name = "COUNTRY")
	private String country;
	
	public Adress() {
		// TODO Auto-generated constructor stub
	}

	public Adress(String street, String city, String country) {
		this.street = street;
		this.city = city;
		this.country = country;
	}

	@Override
	public String toString() {
		return "Adress [adressId=" + adressId + ", street=" + street + ", city=" + city + ", country=" + country + "]";
	}
                   // Set ve Get metotlarını ben sildim siz tanımlayın.

Burada yeni bir sequence oluşturulmasını söyledik.

name olarak verdiğimiz değeri @GeneratedValue generator içinde bildiriyoruz.

sequenceName ise veritabanında oluşturulacak sequence’mizin adı olucak.

initialValue ise bu sequence değeri kaçtan başlayacak onu belirtiyoruz.

 

Student sınıfımıza bakalım.

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.SequenceGenerator;

@Entity
public class Student {

	@Id
	@SequenceGenerator(name = "STUDENT_SEQUENCE_GENERATOR", sequenceName = "STUDENT_SEQUENCE", initialValue = 100)
	@GeneratedValue(generator = "STUDENT_SEQUENCE_GENERATOR")
	@Column(name = "STUDENT_ID")
	private int studentId;
	
	@Column(name = "NAME", unique = false)
	private String name;
	
	@Column(name = "SURNAME")
	private String surname;
	
	@OneToOne
	@JoinColumn(name = "ADRESS_ID")
	private Adress adress;
	
	public Student() {
		// TODO Auto-generated constructor stub
	}

	public Student(String name, String surname, Adress adress) {
		this.name = name;
		this.surname = surname;
		this.adress = adress;
	}

	@Override
	public String toString() {
		return "Student [studentId=" + studentId + ", name=" + name + ", surname=" + surname + ", adress=" + adress
				+ "]";
	}
                 //set ve get tanımlayın, kalabalıgı gidermek için ben sildim.

 

Burada aynı şekilde @SequenceGenerator kullandık ve değerini 100 ile başlamasını söyledikten sonra @GeneratedValue’de bunu bildirdik.

Burada bir başka kullanım ise @JoinColumn, Student tablosuna eklenecek foreign key sütunun adını değiştirdik.

Main metodumuzu ve hibernate.cfg.xml dosyamızda değişiklik yapmadan programızı çalıştırdığımızda..

3.RESİM

 

Tabloda da görüldüğü üzere Adres tablosundan gelen foreign key sütunun adını değiştirdik ve primary key olan kısımları verdiğimiz değerlerden başlattık. @OneToOne hakkında biraz olsun bilgi sahibi olduk.

Bir sonraki konumuz olan @ManyToOne’a bakalım.

@ManyToOne nedir?

Şöyle bir örnek verebiliriz.

Öğrenci <–> Üniversite düşünün ama bu örneğimizde öğrencimizin aynı anda birden fazla Universite’de okumasına izin vermeyeceğiz.

 

4.RESİM

Resimde de görüldüğü üzere birden fazla öğrenci aynı üniversitede okurken aynı öğrenci birden fazla üniversitede okuyamıyor. Bu duruma biz ManyToOne diyoruz. n <–> 1 ilişki

 

Bir önceki örneğimizin içine birde University sınıfı ekleyeceğiz ve onuda @Entity tanımlayacağız.

 

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;

@Entity
public class University {

	@Id
	@SequenceGenerator(name = "UNIVERSITY_SEQUENCE_GENERATOR", sequenceName = "UNIVERSITY_SEQUENCE", initialValue = 1)
	@GeneratedValue(generator = "UNIVERSITY_SEQUENCE_GENERATOR")
        @Column(name = "UNIVERSITY_ID")
	private int universityId;
	
	@Column(name = "NAME", unique = true, length = 30)
	private String name;

	public University() {
		// TODO Auto-generated constructor stub
	}
	
	public University(String name) {
		this.name = name;
	}
	
	@Override
	public String toString() {
		return "University [universityId=" + universityId + ", name=" + name + "]";
	}

             // Set ve get metotlarını tanımlayın. Ben cok yer kaplamasın diye sildim.
}

Burada name propery’in üzerindeki @Column dipnotunda ‘unique =  true’ tanımladım. Burada demek istediğim aynı üniversite isminden birden fazla kayıt olmasın.

 

Yeni bir class açtık ve @Entity olarak tanımladık ve bunu hibernate.cfg.xml dosyasında belirmeyi unutmayınız.

  <mapping class="Student"/>
  <mapping class="Adress"/>
  <mapping class="University"/>

 

Sıradaki işlemimiz ise Student sınıfında University nesnesi oluşturmaya, oluştuduktan sonra constructor içinde parametre olarak tanımlayınız ve yine University sınıfımızın nesnesinin set ve get metotlarını oluşturunuz.

 

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToOne;
import javax.persistence.SequenceGenerator;


@Entity
public class Student {

	@Id
	@SequenceGenerator(name = "STUDENT_SEQUENCE_GENERATOR", sequenceName = "STUDENT_SEQUENCE", initialValue = 100)
	@GeneratedValue(generator = "STUDENT_SEQUENCE_GENERATOR")
	@Column(name = "STUDENT_ID")
	private int studentId;
	
	@Column(name = "NAME", unique = false)
	private String name;
	
	@Column(name = "SURNAME")
	private String surname;
	
	@OneToOne
	@JoinColumn(name = "ADRESS_ID")
	private Adress adress;
	
	@ManyToOne
	@JoinColumn(name = "UNIVERSITY_ID")
	private University university;
	
	public Student() {
		// TODO Auto-generated constructor stub
	}

	public Student(String name, String surname, Adress adress, University university) {
		this.name = name;
		this.surname = surname;
		this.adress = adress;
		this.university = university;
	}

	@Override
	public String toString() {
		return "Student [studentId=" + studentId + ", name=" + name + ", surname=" + surname + ", adress=" + adress
				+ "]";
	}

                      // Set ve Get metotları

}

 

Burada görüldüğü üzeri University nesnesinin üzerinde @ManyToOne şeklinde dipnot kullandık. @JoinColumn ile de  Student tablomuza eklenecek sütunun adını değiştirdik.

 

Adress sınıfımızda bir değişiklik yapmıyoruz. Main metodumuzun bulunduğu class’ta ekleme işlemleri yapacağız.

 

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class Test {

	public static void main(String[] args) {
		
		Adress adress1 = new Adress("Cumhuriyet cad.", "Ankara", "Turkiye");
		Adress adress2 = new Adress("Çankaya cad", "Ankara", "Turkiye");
		Adress adress3 = new Adress("Kazım Karabekir cad.", "Ankara", "Turkiye");
		Adress adress4 = new Adress("Seyhan cad.", "Adana", "Turkiye");
		
		University university1= new University("Dumlupınar Universitesi");
		University university2= new University("Yıldız Teknik Universitesi");
		
		Student student1 = new Student("Ferhat", "Aykan", adress3, university1);
		Student student2 = new Student("Enes", "Çınar", adress1, university2);
		Student student3 = new Student("Uğur", "Baş", adress2, university2);
		Student student4 = new Student("Furkan", "Uslu", adress4, university1);
		
		
		SessionFactory sessionFactory = new Configuration().configure("hibernate.cfg.xml").buildSessionFactory();
		Session session = sessionFactory.openSession();
		
		session.save(student1);
		session.save(student2);
		session.save(student3);
		session.save(student4);
		
		session.save(adress1);
		session.save(adress2);
		session.save(adress3);
		session.save(adress4);
		
		session.save(university2);
		session.save(university1);
		
		session.beginTransaction().commit();
		session.close();
		
	}
}

 

İki tane yeni üniversite eklededikten sonra öğrencilerimizle ilişkilendirdik. Programı çalıştırdığımızda ise.

 

5.RESİM

 

Resimde de görüldüğü gibi 3 tane tablo oluştu ve foreign key’lerimizi student tablosuna ekledik.

 

Bir sonraki dersimizde @OneToMany ve @ManyToMany ilişkilerini inceleyeceğiz.  Bugünlük bu kadar sağlıcakla kalın 🙂

 

Yorum Yap