Showing posts with label MySQL. Show all posts
Showing posts with label MySQL. Show all posts

Sunday, January 22, 2017

mysqldump Yedeklerinin Farklı Bir Sürücüye Geri Getirilmesi

MySQL'de mantıksal yedek almak için mysqldump komutunu kullanıyoruz. mysqldump ile alınan yedeklerde temel olarak create table ve insert into ifadeleri yer alır. mysqldump yedeğinin nasıl farklı bir sürücüye geri getirileceğini inceleyeceğiz. İlk olarak yapılandırma dosyasında innodb_file_per_table = 1 değerinin etkin olduğundan emin olun.  Bu özellik açık olduğunda her InnoDB tablosu için ayrı bir ibd dosyası oluşturulur. Şimdi mysqldump dosyasında create table ifadelerini bulup sonuna DATA DIRECTORY='e:/var/tablespaces' ifadesini ekliyoruz:

CREATE TABLE `city` (
  `ID` int(11) NOT NULL AUTO_INCREMENT,
  `Name` char(35) NOT NULL DEFAULT '',
  `CountryCode` char(3) NOT NULL DEFAULT '',
  `District` char(20) NOT NULL DEFAULT '',
  `Population` int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY (`ID`),
  KEY `CountryCode` (`CountryCode`),
  CONSTRAINT `city_ibfk_1` FOREIGN KEY (`CountryCode`) REFERENCES `country` (`Code`)
) ENGINE=InnoDB AUTO_INCREMENT=4080 
  DEFAULT CHARSET=latin1 
  DATA DIRECTORY='e:/var/tablespaces';

Ardından tabloları getirmek için aşağıdaki adımları gerçekleştiriyoruz:

mysql -uroot -p -e "drop database world"
mysql -uroot -p -e "create database world"
mysql -uroot -p world < world.sql

Böylelikle world veri tabanındaki tabloların ibd dosyaları e:/var/tablespaces dizini altında oluşacaktır:

E:\opt64\mysql-advanced-5.7.17-winx64\bin>cd e:\var\tablespaces

e:\var\tablespaces>dir
 Volume in drive E is SSD
 Volume Serial Number is CAFE-BABE

 Directory of e:\var\tablespaces

01/22/2017  10:22 AM    <DIR>          .
01/22/2017  10:22 AM    <DIR>          ..
01/22/2017  10:23 AM    <DIR>          world
               0 File(s)              0 bytes
               3 Dir(s)  38,019,444,736 bytes free

e:\var\tablespaces>cd world

e:\var\tablespaces\world>dir
 Volume in drive E is SSD
 Volume Serial Number is CAFE-BABE

 Directory of e:\var\tablespaces\world

01/22/2017  10:23 AM    <DIR>          .
01/22/2017  10:23 AM    <DIR>          ..
01/22/2017  10:23 AM           606,208 city.ibd
01/22/2017  10:23 AM           163,840 country.ibd
01/22/2017  10:23 AM           229,376 countrylanguage.ibd
               3 File(s)        999,424 bytes
               2 Dir(s)  38,020,681,728 bytes free



Tuesday, January 10, 2017

MySQL'de Değişkenler

MySQL ilişkisel veritabanı sunucusunda iki tür değişken bulunmaktadır:
  • Veritabanının davranışını okumamızı sağlayan değişkenler (status)
  • Veritabanının davranışını değiştirmemizi sağlayan değişkenler (variable)
Yine bu değişkenler kendi içinde global ve session olmak üzere iki farklı gruba ayrılırlar. Bu değişkenler INFORMATION_SCHEMA veritabanında tablolarda yer alır:

MariaDB [(safirdepo)]> show tables from information_schema like '%STATUS%';
+-----------------------------------------+
| Tables_in_information_schema (%STATUS%) |
+-----------------------------------------+
| GLOBAL_STATUS                           |
| SESSION_STATUS                          |
+-----------------------------------------+
2 rows in set (0.00 sec)

MariaDB [(safirdepo)]> show tables from information_schema like '%VARIAB%';
+-----------------------------------------+
| Tables_in_information_schema (%VARIAB%) |
+-----------------------------------------+
| GLOBAL_VARIABLES                        |
| SESSION_VARIABLES                       |
| SYSTEM_VARIABLES                        |
+-----------------------------------------+
3 rows in set (0.00 sec)

Bu değişkenlerin değerini okumak için yukarıda listelenen tabloları SELECT ile sorgulamak yerine kısayolu olan show komutundan yararlanırız:

MariaDB [(safirdepo)]> show global status like 'ROWS_SENT';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Rows_sent     | 1725  |
+---------------+-------+
1 row in set (0.00 sec)

MariaDB [(safirdepo)]> show session status like 'ROWS_SENT';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Rows_sent     | 1     |
+---------------+-------+
1 row in set (0.00 sec)

MariaDB [(safirdepo)]> select count(*) from INFORMATION_SCHEMA.GLOBAL_STATUS;
+----------+
| count(*) |
+----------+
|      516 |
+----------+
1 row in set (0.01 sec)

MariaDB [(safirdepo)]> select count(*) from INFORMATION_SCHEMA.SESSION_STATUS;
+----------+
| count(*) |
+----------+
|      516 |
+----------+
1 row in set (0.00 sec)

MariaDB [(safirdepo)]> select count(*) from INFORMATION_SCHEMA.SESSION_VARIABLES;
+----------+
| count(*) |
+----------+
|      605 |
+----------+
1 row in set (0.01 sec)

MariaDB [(safirdepo)]> select count(*) from INFORMATION_SCHEMA.GLOBAL_VARIABLES;
+----------+
| count(*) |
+----------+
|      586 |
+----------+
1 row in set (0.00 sec)

Değişkenlerin değerini değiştirmek için set komutundan yararlanıyoruz:

MariaDB [(safirdepo)]> set session SQL_MODE = 'TRADITIONAL';Query OK, 0 rows affected (0.00 sec)

MariaDB [(safirdepo)]> select * from INFORMATION_SCHEMA.SESSION_VARIABLES where variable_name like '%MODE%';
+--------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------+
| VARIABLE_NAME            | VARIABLE_VALUE                                                                                                                                       |
+--------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------+
| WSREP_GTID_MODE          | OFF                                                                                                                                                  |
| SQL_MODE                 | STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |
| INNODB_STRICT_MODE       | OFF                                                                                                                                                  |
| INNODB_AUTOINC_LOCK_MODE | 1                                                                                                                                                    |
| PSEUDO_SLAVE_MODE        | OFF                                                                                                                                                  |
| SLAVE_DDL_EXEC_MODE      | IDEMPOTENT                                                                                                                                           |
| SLAVE_EXEC_MODE          | STRICT                                                                                                                                               |
| GTID_STRICT_MODE         | OFF                                                                                                                                                  |
| OLD_MODE                 |                                                                                                                                                      |
| SLAVE_PARALLEL_MODE      | conservative                                                                                                                                         |
+--------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------+
10 rows in set (0.00 sec)

MariaDB [(safirdepo)]> set session SQL_MODE = 'TRADITIONAL';Query OK, 0 rows affected (0.00 sec)

MariaDB [(safirdepo)]> select @@SQL_MODE;
+------------------------------------------------------------------------------------------------------------------------------------------------------+
| @@SQL_MODE                                                                                                                                           |
+------------------------------------------------------------------------------------------------------------------------------------------------------+
| STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |
+------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

MariaDB [(safirdepo)]> select @@session.SQL_MODE;
+------------------------------------------------------------------------------------------------------------------------------------------------------+
| @@session.SQL_MODE                                                                                                                                   |
+------------------------------------------------------------------------------------------------------------------------------------------------------+
| STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |
+------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.01 sec)

MariaDB [(nsafirdepoone)]> select @@global.SQL_MODE;
+--------------------------------------------+
| @@global.SQL_MODE                          |
+--------------------------------------------+
| NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |
+--------------------------------------------+
1 row in set (0.01 sec)

Değişkenlerin bir kısmını canlı sistemde değiştirmek mümkün değildir:
mysql> set global innodb_log_file_size=5000;

ERROR 1238 (HY000): Variable 'innodb_log_file_size' is a read only variable

Üretim ortamında tavsiye etmemekle beraber değişkenlerin bazıları doğrudan bellek gözüne erişerek değiştirmek mümkündür. Aşağıdaki örnekte tüm bağlantıların dolu olduğu bir MySQL sunucusunda GNU hata ayıklayıcısı (=debugger) kullanılarak max_connections değişkeni değiştiriliyor:

[centos@server1 ~]$ mysql -uroot -proot
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 3
Server version: 10.1.11-MariaDB MariaDB Server

Copyright (c) 2000, 2015, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> show global variables like 'max_c%';
+--------------------+-------+
| Variable_name      | Value |
+--------------------+-------+
| max_connect_errors | 100   |
| max_connections    | 151   |
+--------------------+-------+
2 rows in set (0.00 sec)

MariaDB [(none)]> exit
Bye
[centos@server1 ~]$ sudo gdb -p 1269 -ex "set max_connections=4096" -batch
[sudo] password for centos: 
[New LWP 1444]
[New LWP 1443]
[New LWP 1442]
[New LWP 1441]
[New LWP 1440]
[New LWP 1439]
[New LWP 1438]
[New LWP 1436]
[New LWP 1435]
[New LWP 1434]
[New LWP 1433]
[New LWP 1432]
[New LWP 1405]
[New LWP 1404]
[New LWP 1403]
[New LWP 1402]
[New LWP 1401]
[New LWP 1400]
[New LWP 1399]
[New LWP 1398]
[New LWP 1397]
[New LWP 1396]
[New LWP 1367]
[New LWP 1314]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
0x00007f71a9ea464d in poll () from /lib64/libc.so.6
[centos@server1 ~]$ mysql -uroot -proot
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 4
Server version: 10.1.11-MariaDB MariaDB Server

Copyright (c) 2000, 2015, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> show global variables like 'max_c%';
+--------------------+-------+
| Variable_name      | Value |
+--------------------+-------+
| max_connect_errors | 100   |
| max_connections    | 4096  |
+--------------------+-------+
2 rows in set (0.00 sec)

Sunday, August 7, 2016

World Veritabanının JPA 2.1 Modeli


   MySQL açık kaynak kodlu, (Oracle, MariaDB, Percona gibi) firmalardan desteğini alabileceğiniz, yaygın ve çok ölçekli (Facebook, Google, Twitter, Linkedin ve Alibaba gibi) kullanımı olan ilişkisel bir veri tabanıdır. Oracle tarafından sunulan MySQL eğitimlerinde ve sertifikasyon sınavındaki sorularda sıklıkla kullanılan bir veri tabanı vardır: World. World veritabanını bu bağlantıdan indirebilirsiniz. Veritabanının kurulumunu, aşağıdaki adımları takip ederek kolaylıkla tamamlayabilirsiniz:
mysql> set session autocommit=0;
Query OK, 0 rows affected (0.00 sec)

mysql> create database world;
Query OK, 1 row affected (0.00 sec)

mysql> use world
Database changed
mysql> source c:/tmp/world.sql

. . . . . . . . . . . . . . . . . . .
Query OK, 1 row affected (0.00 sec)

Query OK, 1 row affected (0.00 sec)

Query OK, 1 row affected (0.00 sec)

Query OK, 0 rows affected (0.02 sec)

Query OK, 0 rows affected (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

   world veri tabanında dünya ülkeleri, şehirler ve konuşulan diller ile ilgili bilgiler üç tabloda toplanmıştır:
mysql> use world
Database changed
mysql> show tables;
+-----------------+
| Tables_in_world |
+-----------------+
| city            |
| country         |
| countrylanguage |
+-----------------+
3 rows in set (0.00 sec)

mysql> desc city;
+-------------+----------+------+-----+---------+----------------+
| Field       | Type     | Null | Key | Default | Extra          |
+-------------+----------+------+-----+---------+----------------+
| ID          | int(11)  | NO   | PRI | NULL    | auto_increment |
| Name        | char(35) | NO   |     |         |                |
| CountryCode | char(3)  | NO   | MUL |         |                |
| District    | char(20) | NO   |     |         |                |
| Population  | int(11)  | NO   |     | 0       |                |
+-------------+----------+------+-----+---------+----------------+
5 rows in set (0.01 sec)

mysql> desc country;
+----------------+---------------------------------------------------------------------------------------+------+-----+---------+-------+
| Field          | Type                                                                                  | Null | Key | Default | Extra |
+----------------+---------------------------------------------------------------------------------------+------+-----+---------+-------+
| Code           | char(3)                                                                               | NO   | PRI |         |       |
| Name           | char(52)                                                                              | NO   |     |         |       |
| Continent      | enum('Asia','Europe','North America','Africa','Oceania','Antarctica','South America') | NO   |     | Asia    |       |
| Region         | char(26)                                                                              | NO   |     |         |       |
| SurfaceArea    | float(10,2)                                                                           | NO   |     | 0.00    |       |
| IndepYear      | smallint(6)                                                                           | YES  |     | NULL    |       |
| Population     | int(11)                                                                               | NO   |     | 0       |       |
| LifeExpectancy | float(3,1)                                                                            | YES  |     | NULL    |       |
| GNP            | float(10,2)                                                                           | YES  |     | NULL    |       |
| GNPOld         | float(10,2)                                                                           | YES  |     | NULL    |       |
| LocalName      | char(45)                                                                              | NO   |     |         |       |
| GovernmentForm | char(45)                                                                              | NO   |     |         |       |
| HeadOfState    | char(60)                                                                              | YES  |     | NULL    |       |
| Capital        | int(11)                                                                               | YES  |     | NULL    |       |
| Code2          | char(2)                                                                               | NO   |     |         |       |
+----------------+---------------------------------------------------------------------------------------+------+-----+---------+-------+
15 rows in set (0.01 sec)

mysql> desc countrylanguage;
+-------------+---------------+------+-----+---------+-------+
| Field       | Type          | Null | Key | Default | Extra |
+-------------+---------------+------+-----+---------+-------+
| CountryCode | char(3)       | NO   | PRI |         |       |
| Language    | char(30)      | NO   | PRI |         |       |
| IsOfficial  | enum('T','F') | NO   |     | F       |       |
| Percentage  | float(4,1)    | NO   |     | 0.0     |       |
+-------------+---------------+------+-----+---------+-------+
4 rows in set (0.01 sec)

   Bu tablolar arasındaki bağlantıyı varlık-ilişki çizgesi ile görsel olarak daha kolay kavrayabiliriz:

   Java Persistence API (JPA) ile tabloları, tablolar arasındaki yukarıdaki çizgede tanımlanan ilişkileri ile birlikte Java sınıflarına karşı düşürebilir, nesneye dayalı yaklaşımla modelleyebiliriz:

Country.java:
package com.example.world.entity;

import java.io.Serializable;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.NamedAttributeNode;
import javax.persistence.NamedEntityGraph;
import javax.persistence.NamedEntityGraphs;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.NamedSubgraph;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;

@Entity
@NamedQueries({ 
  @NamedQuery(
        name = "AllFromCountry", 
        query = "select c from Country c"
  ),
  @NamedQuery(
        name = "ByContinentFromCountry", 
        query = "select c from Country c where c.continent=:continent"
  ) 
})
@NamedEntityGraphs({
  @NamedEntityGraph(
        name = "graph.Country.cities", 
        attributeNodes = @NamedAttributeNode(value = "cities", subgraph = "cities") , 
        subgraphs = @NamedSubgraph(
               name = "cities", 
               attributeNodes = @NamedAttributeNode("country") 
        ) 
  ),
  @NamedEntityGraph(
        name = "graph.Country.citylangs", 
        attributeNodes =  
           { 
             @NamedAttributeNode(value = "cities", subgraph = "cities") ,
             @NamedAttributeNode(value = "languages", subgraph = "languages")              
           },
        subgraphs = {
             @NamedSubgraph(
                    name = "cities", 
                    attributeNodes = @NamedAttributeNode("country")
             ), 
             @NamedSubgraph(
                    name = "languages", 
                    attributeNodes = @NamedAttributeNode("country")
             ), 
        }                   
  ),
  @NamedEntityGraph(
        name = "graph.Country.languages", 
        attributeNodes = @NamedAttributeNode(value = "languages", subgraph = "languages") , 
        subgraphs = @NamedSubgraph(
                name = "languages", 
                attributeNodes = @NamedAttributeNode("country") 
        ) 
  ) 
})
public class Country implements Serializable {
 @Id
 private String code;
 private String name;
 private int population;
 @Column(name = "surfacearea")
 private double surfaceArea;
 private String continent;

 @JoinColumn(name = "capital", nullable = false, updatable = false, insertable = false)
 @OneToOne(cascade={CascadeType.MERGE})
 private City capital;

 @OneToMany(mappedBy = "country",orphanRemoval=true)
 private Set<City> cities;

 @OneToMany(mappedBy = "country",orphanRemoval=true)
 private Set<CountryLanguage> languages;

 public Country() {
 }

 // getters and setters

 @Override
 public String toString() {
  return "Country [code=" + code + ", name=" + name + ", population=" + population + ", surfaceArea="
    + surfaceArea + ", continent=" + continent + ", capital=" + capital + ", cities=" + cities
    + ", languages=" + languages + "]";
 }


}

City.java:
package com.example.world.entity;

import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToOne;

@Entity
@NamedQueries({
 @NamedQuery(name="fromCity.all",query="select c from City c"),
 @NamedQuery(name="fromCity.byCountry",query="select c from City c where c.country.code=:code")
})
public class City {
 @Id
 private int id;
 private String name;
 private Integer population;

 @JoinColumn(name = "countrycode", nullable = true,insertable=false,updatable=false)
 @OneToOne(fetch = FetchType.LAZY)
 private Country country;

 public City() {
 }

 // getters and setters

 @Override
 public String toString() {
  return "City [id=" + id + ", name=" + name + ", population=" + population + ", country name="
    + country.getName() + "]";
 }

}

CountryLanguagePK.java:
package com.example.world.entity;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Embeddable;

@Embeddable
public class CountryLanguagePK implements Serializable {
 @Column(nullable=false)
 private String language;
 @Column(name = "countrycode",nullable=false)
 private String code;

 public CountryLanguagePK() {
 }

 public CountryLanguagePK(String language, String code) {
  this.language = language;
  this.code = code;
 }

 // getters and setters

 @Override
 public String toString() {
  return "CountryLanguagePK [language=" + language + ", code=" + code + "]";
 }

}

CountryLanguage.java:
package com.example.world.entity;

import javax.persistence.Column;
import javax.persistence.Convert;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;

import com.example.world.entity.converter.BooleanCharacterConverter;

@Entity
public class CountryLanguage {
 @EmbeddedId
 private CountryLanguagePK countryLanguagePK;
 @Column(name = "isOfficial")
 @Convert(converter = BooleanCharacterConverter.class)
 private boolean official;
 private double percentage;

 @OneToOne()
 @JoinColumn(name = "countrycode", insertable = false, updatable = false, nullable = false)
 private Country country;

 public CountryLanguage() {
 }

 // getters and setters

 @Override
 public String toString() {
  return "CountryLanguage [countryLanguagePK=" + countryLanguagePK + ", official=" + official + ", percentage="
    + percentage + "]";
 }

}

BooleanCharacterConverter.java:
package com.example.world.entity.converter;

import javax.persistence.AttributeConverter;
import javax.persistence.Converter;

@Converter
public class BooleanCharacterConverter implements AttributeConverter<Boolean, String>{

 @Override
 public String convertToDatabaseColumn(Boolean value) {
  return value ? "T" : "F";
 }

 @Override
 public Boolean convertToEntityAttribute(String value) {
  return "T".equals(value);
 }


}

   Java sınıflarını, veri tabanındaki tablolara karşı düşürürken, Java programlama diline Java SE 5 ile gelen notlardan (=annotation) yararlanıyoruz. Mutlaka kullanmamız gereken iki not bulunuyor: @Entity ve @Id. @Entitiy notu ile sınıfın kalıcı olması gereken ve yaşam döngüsünün JPA tarafından yönetilen bir sınıf olduğunun notunu düşmüş oluyoruz. Her ne kadar veri tabanında her tabloda bir birincil anahtar bulunma zorunluluğu bulunmasa da eğer JPA ile çalışıyorsanız tablonun mutlaka bir ya da daha fazla alandan oluşan bir birincil anahtarı (=primary key) bulunması gerekir. Bu birincil anahtara karşı düşen öz niteliğe @Id notunu düşüyoruz. Eğer birincil anahtar birden fazla alandan oluşuyor ise buna bileşik birincil anahtar (=composite primary key) adını veriyoruz. Bileşik birincil anahtarları iz düşürürken kullanılan yöntemlerden biri, ilk olarak, bu birden fazla birincil anahtar için iz düşüreceğimiz öz niteliklerin olduğu ayrı bir sınıf oluşturmak ve bu sınıfa @Embeddable notunu düşmektir. Daha sonra bu sınıftan bir öz nitelik, @Entity notunu düştüğümüz sınıfta @EmbeddedId notu ile tanımlanır. Bunun bir uygulamasını CountryLanguagePK ve CountryLanguage sınıflarında bulabilirsiniz.
   JPA'da tüm kalıcılık işlemleri için EntityManager arayüzünü kullanıyoruz. JPA aslında kalıcılık problemini çözen bir kod içermiyor. Kalıcılık problemi ile ilgilenen çözümler ile uygulama kodumuz arasında bir arayüz sağlıyor. Bu nedenle JPA tabanlı çözümde mutlaka bir JPA gerçeklemesine gereksinim duyarız. Bu gereksinimi Hibernate, Eclipselink ya da OpenJPA gibi kütüphaneler ile karşılayabiliriz. Maven kullananlar için bu kütüphanelerin bağımlılıklarını pom.xml'e eklemeniz gerekir:
  • Hibernate 5.2 için
<dependency>
 <groupId>org.hibernate</groupId>
 <artifactId>hibernate-core</artifactId>
 <version>5.2.1.Final</version>
</dependency>
  • EclipseLink 2.6 için
<dependency>
 <groupId>org.eclipse.persistence</groupId>
 <artifactId>eclipselink</artifactId>
 <version>2.6.3</version>
</dependency>

JPA konfigürasyonu için adı ve yeri standart olan bir dosya bulunuyor: META-INF/persistence.xml:
  • Hibernate 5 kullananlar için
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1"
 xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
 <persistence-unit name="worldPU" transaction-type="RESOURCE_LOCAL">
                <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
         <class>com.example.world.entity.Country</class>
         <class>com.example.world.entity.City</class>
         <class>com.example.world.entity.CountryLanguage</class>
         <class>com.example.world.entity.CountryLanguagePK</class>
         <class>com.example.world.entity.converter.BooleanCharacterConverter</class>
         <properties>
          <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/world" />
          <property name="javax.persistence.jdbc.user" value="root" />
          <property name="javax.persistence.jdbc.password" value="root" />
          <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
          <property name="hibernate.show_sql" value="true" />
          <property name="hibernate.format_sql" value="true" />
          <property name="hibernate.enable_lazy_load_no_trans" value="true" /> 
         </properties>
 </persistence-unit>
</persistence>
  • EclipseLink 2.6 kullananlar için
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1"
 xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
 <persistence-unit name="worldPU" transaction-type="RESOURCE_LOCAL">
  <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
  <class>com.example.world.entity.Country</class>
  <class>com.example.world.entity.City</class>
  <class>com.example.world.entity.CountryLanguage</class>
  <class>com.example.world.entity.CountryLanguagePK</class>
  <class>com.example.world.entity.converter.BooleanCharacterConverter</class>
  <properties>
   <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/world" />
   <property name="javax.persistence.jdbc.user" value="root" />
   <property name="javax.persistence.jdbc.password" value="root" />
   <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
   <property name="eclipselink.logging.level.sql" value="FINE" />
   <property name="eclipselink.logging.parameters" value="true" />
  </properties>
 </persistence-unit>
</persistence>

Şimdi kalıcılık işlemlerini tanımlayacağımız Data Access Object (DAO) arayüzlerini ve bu arayüzleri EntityManager kullanarak gerçekleyeceğimiz sınıfları kodlayalım:

GenericDao.java:
package com.example.world.dao;

import java.util.Collection;

public interface GenericDao<Entity,Key> {
 Entity add(Entity country);
 Entity update(Entity country);
 Entity remove(Key key);
 Entity find(Key key);
 Entity find(Key key,String graphName);
 Collection<Entity> findAll();
}

CountryDao.java:
package com.example.world.dao;

import java.util.Collection;

import com.example.world.entity.Country;

public interface CountryDao extends GenericDao<Country, String> {
 Collection<Country> findByContinent(String continent);
}

CityDao.java:
package com.example.world.dao;

import java.util.Collection;

import com.example.world.entity.City;

public interface CityDao extends GenericDao<City, Integer>{
 Collection<City> findCitiesByCountry(String code);
}

CountryLanguageDao.java:
package com.example.world.dao;

import com.example.world.entity.CountryLanguage;
import com.example.world.entity.CountryLanguagePK;

public interface CountryLanguageDao extends GenericDao<CountryLanguage, CountryLanguagePK> {
}

JpaCountryDao.java:
package com.example.world.dao.impl;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import javax.persistence.EntityGraph;
import javax.persistence.EntityManager;

import com.example.world.dao.CountryDao;
import com.example.world.entity.Country;

public class JpaCountryDao implements CountryDao {

 private EntityManager entityManager;

 public void setEntityManager(EntityManager entityManager) {
  this.entityManager = entityManager;
 }

 @Override
 public Country add(Country country) {
  entityManager.persist(country);
  return country;
 }

 @Override
 public Country update(Country country) {
  entityManager.merge(country);
  return country;
 }

 @Override
 public Country remove(String code) {
  Country found = entityManager.find(Country.class, code);
  if (found != null) {
   entityManager.remove(found);
  }
  return found;
 }

 @Override
 public Country find(String code) {
  return entityManager.find(Country.class, code);
 }

 @Override
 public Collection<Country> findAll() {
  return entityManager.createNamedQuery("AllFromCountry", Country.class).getResultList();
 }

 @Override
 public Collection<Country> findByContinent(String continent) {
  return entityManager.createNamedQuery("ByContinentFromCountry", Country.class)
    .setParameter("continent", continent).getResultList();
 }

 @Override
 public Country find(String key, String graphName) {  
  EntityGraph<?> eg= entityManager.getEntityGraph(graphName);
  Map<String,Object> props= new HashMap<>();
  props.put("javax.persistence.fetchgraph", eg);
  return entityManager.find(Country.class, key, props);
 }

}

JpaCityDao.java:
package com.example.world.dao.impl;

import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.EntityGraph;
import javax.persistence.EntityManager;

import com.example.world.dao.CityDao;
import com.example.world.entity.City;

public class JpaCityJpaDao implements CityDao {
 private EntityManager entityManager;

 public void setEntityManager(EntityManager entityManager) {
  this.entityManager = entityManager;
 }

 @Override
 public City add(City country) {
  entityManager.persist(country);
  return country; 
 }

 @Override
 public City update(City country) {
  return entityManager.merge(country);
 }

 @Override
 public City remove(Integer key) {
  City city;
  city = entityManager.find(City.class, key);
  if (city != null) {
   entityManager.remove(city);
  }
  return city;
 }

 @Override
 public City find(Integer key) {
  City city = entityManager.find(City.class, key);
  return city;
 }

 @Override
 public Collection<City> findAll() {
  List<City> cities = 
    entityManager.createNamedQuery("fromCity.all", City.class)
                 .getResultList();
  return cities;
 }

 @Override
 public Collection<City> findCitiesByCountry(String code) {
  List<City> cities = entityManager.createNamedQuery("fromCity.byCountry", City.class)
                             .setParameter("code", code)
                             .getResultList();
  return cities;
 }

 @Override
 public City find(Integer key, String graphName) {
  EntityGraph<?> eg= entityManager.getEntityGraph(graphName);
  Map<String,Object> props= new HashMap<>();
  props.put("javax.persistence.fetchgraph", eg);
  return entityManager.find(City.class, key, props);
 }

}

JpaCountryLanguageDao.java:
package com.example.world.dao.impl;

import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.EntityGraph;
import javax.persistence.EntityManager;

import com.example.world.dao.CountryLanguageDao;
import com.example.world.entity.CountryLanguage;
import com.example.world.entity.CountryLanguagePK;

public class JpaCountryLanguageDao implements CountryLanguageDao {

 private EntityManager entityManager;
 
 public void setEntityManager(EntityManager entityManager) {
  this.entityManager = entityManager;
 }

 @Override
 public CountryLanguage add(CountryLanguage countryLanguage) {
  entityManager.persist(countryLanguage);
  return countryLanguage;
 }

 @Override
 public CountryLanguage update(CountryLanguage countryLanguage) {
  return entityManager.merge(countryLanguage);
}
@Override public CountryLanguage remove(CountryLanguagePK key) { CountryLanguage countryLanguage= entityManager.find(CountryLanguage.class, key); if (countryLanguage!=null) entityManager.remove(countryLanguage); return countryLanguage; } @Override public CountryLanguage find(CountryLanguagePK key) { return entityManager.find(CountryLanguage.class, key); } @Override public Collection<CountryLanguage> findAll() { List<CountryLanguage> languages = entityManager .createQuery("select cl from CountryLanguage cl", CountryLanguage.class) .getResultList(); return languages; } @Override public CountryLanguage find(CountryLanguagePK key, String graphName) { EntityGraph<?> eg= entityManager.getEntityGraph(graphName); Map<String,Object> props= new HashMap<>(); props.put("javax.persistence.fetchgraph", eg); return entityManager.find(CountryLanguage.class, key, props); } }