Doctrine データ永続化のタイミングとUnit of Work
最近は業務でsymfonyを利用している.
symfonyが標準で利用するORM Doctrine
の永続化周りについて少し学んだのでメモ.
日本語のこの記事が分かりやすかった.
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
という考え方を利用している.
これは, objectレベルのトランザクションのようなもの, と表現されている.
自分の中では, Entityに対する一連の変更を Unit of Work
という単位で保持しておき, commit時に実際にDBに適応する, という理解.
Unit of Work
は, EntityManagerが初期作成された時, もしくは flush()
が実行された時に生成される.
flush()
が実行された時にDBに対する反映が行われる.
flush()
が呼び出されない限りは, persist
やremove(objectの削除)
といったUnit of Workに記録されたEntityに関する操作はDBに反映されない.
flush()
されずに, close()
や新たなEntityManagerが生成された場合はUnit of Workに記録された一連の変更を破棄する.
ちょっとかしこくなった