Doctrine データ永続化のタイミングとUnit of Work

最近は業務でsymfonyを利用している. symfonyが標準で利用するORM Doctrineの永続化周りについて少し学んだのでメモ.

日本語のこの記事が分かりやすかった.

ja.stackoverflow.com

Doctrineのデータ永続化のタイミング

そもそも Doctrineとは

いわゆる ORM.

詳しくはこちら :
Home — Doctrine Project

Doctrineを利用することで, DBのTableとSymfonyのEntity間でデータのマッピングを行うことができる. SymfonyのEntityに @ORM\ Annotationでデータマッピング設定を書くことでDoctrineがマッピングを行ってくれる. 素敵.


Entity Managerのお仕事

詳しくはこちら :
Databases and the Doctrine ORM (current)

DoctrineではEntity Managerと呼ばれるマネージャで, objectの状態管理を行う. ここでのobjectはDBの1レコードを表しているという理解. DoctrineからDBに対する操作を行う際, 必ずこのマネージャにobjectを登録する必要がある.

Entity Managerへの登録操作が persist($obj) メソッド. persist(永続化)と行っておきながらこの時, DBに対するsqlは発行されない.

実際のDBへのSQL発行(永続化)は flush() メソッドによって行われる. このメソッドが呼ばれた時に, 実際のクエリが発行される.

7. Working with Objects — Doctrine 2 ORM 2 documentation

7.3 Persisting entities

Invoking the persist method on an entity does NOT cause an immediate SQL INSERT to be issued on the database.
Doctrine applies a strategy called “transactional write-behind”, which means that it will delay most SQL commands until EntityManager#flush() is invoked which will then issue all necessary SQL statements to synchronize your objects with the database in the most efficient way and a single, short transaction, taking care of maintaining referential integrity.

An entity can be made persistent by passing it to the EntityManager#persist($entity) method. 
By applying the persist operation on some entity, that entity becomes MANAGED, which means that its persistence is from now on managed by an EntityManager. 
As a result the persistent state of such an entity will subsequently be properly synchronized with the database when EntityManager#flush() is invoked.

Unit of Workのライフサイクル

DoctrineではUnit Of Workという考え方を利用している.

http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/working-with-objects.html#working-with-objects

これは, objectレベルのトランザクションのようなもの, と表現されている.

自分の中では, Entityに対する一連の変更を Unit of Workという単位で保持しておき, commit時に実際にDBに適応する, という理解.

Unit of Work は, EntityManagerが初期作成された時, もしくは flush()が実行された時に生成される.

flush() が実行された時にDBに対する反映が行われる. flush()が呼び出されない限りは, persistremove(objectの削除)といったUnit of Workに記録されたEntityに関する操作はDBに反映されない.

flush()されずに, close()や新たなEntityManagerが生成された場合はUnit of Workに記録された一連の変更を破棄する.

ちょっとかしこくなった