Əsas məzmuna keçin

Hibernate Dərin Baxış

Hibernate, JPA spesifikasiyasının ən geniş istifadə edilən implementasiyalarından biridir (lakin JPA-dan əvvəl mövcud idi və daha aşağı səviyyəli imkanlar təqdim edir). Bu sənəd Spring Data JPA səviyyəsindən daha dərin Hibernate xüsusiyyətlərini izah edir.

Hibernate vs JPA

MövzuJPAHibernate
StandartSpecification APIImplementation + əlavə extension-lar
QueryJPQLHQL (JPQL super-set)
CriteriaCriteria APICriteria + Hibernate-ə xas özelliklər
Cache strategiyalarıÜmumi interfeysƏtraflı provider xüsusiyyətləri
NaturalIdStandarta daxil deyilDəstək var
Multi-TenantMəhdudDaha çox pattern

Əsas Arxitektura

Terminİzah
SessionEntityManager analoqu (stateful)
SessionFactoryApplication-wide, thread-safe, heavyweight obyekt
Persistence ContextManaged entity-lərin dəqiq snapshot-u
Dirty CheckingDəyişən sahələrin avtomatik aşkarlanması
FlushDəyişikliklərin SQL-ə çevrilib DB-yə göndərilməsi
Flush ModeAUTO, COMMIT, MANUAL

Session Yaratma (Standalone)

Koda bax
Configuration cfg = new Configuration().configure(); // hibernate.cfg.xml
ServiceRegistry registry = new StandardServiceRegistryBuilder()
.applySettings(cfg.getProperties()).build();
SessionFactory sf = cfg.buildSessionFactory(registry);
try(Session session = sf.openSession()){
Transaction tx = session.beginTransaction();
// iş
tx.commit();
}

Flush Davranışı

Flush ModeNə Zaman Flushİstifadə
AUTOSorğu əvvəlində / transaction sonundaDefault
COMMITYalnız commit zamanıPerformans artımı, lakin stale read riski
MANUALƏl ilə flush() çağırışıXüsusi bulk əməliyyatlar

Dirty Checking Mexanizmi

Hibernate entity snapshot saxlayır. Getter/setter ilə dəyişən sahələr commit zamanı müqayisə edilir. Final/primitive dəyişmələri düzgün dizayn et. @DynamicUpdate əlavə sütun sayını azalda bilər.

Entity Mapping Genişlənmələri

Hibernate AnnotasiyasıMəqsəd
@TypeCustom tip map
@NaturalIdTəbii unikal açar
@FormulaVirtual sütun (subquery expression)
@CreationTimestampAvtomatik timestamp
@UpdateTimestampUpdate zamanı timestamp
@BatchSizeBatch loading hint
Koda bax
@Entity
@BatchSize(size = 20)
class Product {
@Id @GeneratedValue Long id;

@NaturalId
@Column(unique = true, nullable = false)
private String sku;

@Formula("(select avg(r.rating) from review r where r.product_id = id)")
private Double avgRating;
}

İnheritence Strategiyaları

StrategiyaAnnotasiyaÜstünlükÇatışmazlıq
Single Table@Inheritance(SINGLE_TABLE)Performans, az joinSütun israfı, nullable-lar
Joined@Inheritance(JOINED)NormalizasiyaJoin overhead
Table Per Class@Inheritance(TABLE_PER_CLASS)Ayrı cədvəllərUnion sorğuları bahalı

Koleksiya Tipləri

TipDavranış
ListOrder saxlanır (ORDER BY / @OrderColumn)
SetUnikal elementlər
MapKey-value (join table ilə)
SortedSet/SortedMapComparable tələb

Fetch Strategiyaları (Hibernate Əlavələri)

Mexanizmİzah
@BatchSizeEyni tip LAZY obyektləri IN (...) ilə yükləyir
SUBSELECTİlk sorğudan sonra qalanları subselect ilə çəkir
SECOND LEVEL CACHELAZY obyekt DB əvəzinə cache-dən

İkinci Səviyyə Cache (2LC)

Layerİzah
1-ci (Session)Transaction scope
2-ciSessionFactory scope
Query CacheSorğunun nəticə ID-lərini saxlayır

Cache Strategiyaları

StrategiyaMəqsəd
READ_ONLYDəyişməyən data (lookup tables)
READ_WRITEKonsistent yazma/oxuma
NONSTRICT_READ_WRITEZəif konsistensiya, daha sürətli
TRANSACTIONALJTA səviyyəli sərt konsistensiya
Koda bax
<!-- hibernate.cfg.xml -->
<property name="hibernate.cache.use_second_level_cache">true</property>
<property name="hibernate.cache.region.factory_class">org.hibernate.cache.jcache.JCacheRegionFactory</property>
<property name="hibernate.javax.cache.provider">org.ehcache.jsr107.EhcacheCachingProvider</property>

Query API-ları

APIÜstünlük
HQLEntity yönümlü
CriteriaDinamik tip təhlükəsiz
Native SQLPerformans kritik / xüsusi funksiyalar
Statik Named QueryReuse + startup yoxlanışı
Koda bax
List<Product> list = session.createQuery("from Product p where p.price > :min", Product.class)
.setParameter("min", 100)
.setMaxResults(50)
.list();

Scrollable Results / Streaming

Böyük dataset-lərdə memory istifadəsini reduce etmək üçün.

Koda bax
ScrollableResults results = session.createQuery("from Order", Order.class)
.setFetchSize(50)
.scroll(ScrollMode.FORWARD_ONLY);
while(results.next()){
Order o = (Order) results.get()[0];
// prosess
if(results.getRowNumber() % 50 == 0){
session.clear(); // memory təmizlə
}
}

Batch Operations

Texnikaİzah
JDBC batchhibernate.jdbc.batch_size
StatelessSession1-ci səviyyə cache olmadan sürətli bulk
Session#clearMemory blow-up qarşısı
Koda bax
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
for(int i=0;i<10_000;i++){
User u = new User();
u.setUsername("u"+i);
session.persist(u);
if(i % 50 == 0){
session.flush();
session.clear();
}
}
tx.commit();

Interceptor və Event Sistemi

MexanizmMəqsəd
InterceptorLifecycle hook-lar (onSave, onDelete)
EventListenerDaha granular event-lər
EntityListenerJPA səviyyəli (@PrePersist ...)
Koda bax
public class AuditInterceptor extends EmptyInterceptor {
@Override
public boolean onFlushDirty(Object entity, Serializable id, Object[] currentState,
Object[] previousState, String[] propertyNames, Type[] types) {
if(entity instanceof Auditable a){
a.setUpdatedAt(Instant.now());
}
return false;
}
}

Natural ID Lookup

Koda bax
Product p = session.byNaturalId(Product.class)
.using("sku", "ABC-123")
.load();

Multi-Tenancy Yanaşmaları

Modelİzah
Separate DBHər tenant üçün ayrıca DB
Separate SchemaEyni DB, fərqli schema
Discriminator ColumnTək cədvəl, tenant_id sütunu

Discriminator modeli sadə, lakin data izoləsi zəif; ayrı DB modeli güclü, amma əməliyyat yükü çox.

Locking Strategiyaları

StrategiyaAnnotasiyaİstifadə
Optimistic@VersionKonflikt az
PessimisticLockMode.PESSIMISTIC_WRITEYüksək yarış
Optimistic Force IncrementLockMode.OPTIMISTIC_FORCE_INCREMENTVersiya artırma məcburi
Koda bax
Order o = session.find(Order.class, id, LockMode.PESSIMISTIC_WRITE);

SQL Output Tənzimləmə

ParametrEffekti
hibernate.show_sqlKonsolda SQL
hibernate.format_sqlOxunaqlı format
hibernate.highlight_sqlRəngli (Hibernate 6)
hibernate.generate_statisticsMetriklər və log

Performance Check List

  • LAZY default saxla (EAGER-i azaldır)
  • Fetch join + limit (cartesian explosion olmasın)
  • Batch size (hibernate.default_batch_fetch_size = 16/32)
  • İkinci səviyyə cache yalnız read-most üçün
  • Hər 50-100 entity-də flush/clear bulk zamanı
  • Projections: DTO (entity tam yükləmək əvəzinə)
  • StatelessSession bulk insert

Tipik Anti-Patternlər

ProblemNəticə
Açıq Session UI (OSIV) sui-istifadəGec DB çağırışları, sürpriz sorğular
EAGER chain-lərŞişmiş SELECT, N+1 zənciri
Hər sorğuda yeni SessionFactoryStartup cost + memory
Çox böyük bir transactionLock müddətinin artması
Random flush çağırışlarıGözlənilməz performans

Sual-Cavab

SualCavab
JPA-dan niyə aşağı səviyyəyə enim?Xüsusi optimizasiya / extension ehtiyacı
StatelessSession nə verir?1-ci səviyyə cache/dirty checking yoxdur → sürət
Query cache nə saxlayır?ID siyahısı (entity-lər ayrıca 2LC-dən yüklənir)
NaturalId üstünlüyü?Alternativ unikal açar ilə tez lookup
flush() nə edir?Change Set → SQL generation & execution

Ən Yaxşı Təcrübələr

  • SessionFactory-ni application lifecycle boyu reuse et
  • Monitoring: generate_statistics=true ilə lokal analiz → prod-da metric exporter istifadə et
  • Domain modelini aggregate sərhədləri ilə dizayn et (lazımsız uzun obyekt qrafı yükləmə)
  • Custom tip üçün AttributeConverter və ya @Type istifadə et
  • Sorğu sayı və ölçüsünü profil et (p95/p99 latency)

Növbəti Addım

Hibernate biliklərini möhkəmləndirmək üçün: spring/jpa sənədini yenidən nəzərdən keçir və DB dizayn optimallaşdırması üçün database/indeksler bölməsinə bax.