DQL is now a real language inside Doctrine, based on an EBNF that is parsed and transformed to SQL. Benefits of this refactoring are readable error messages, the generation of an AST that allows us to support many different vendors and powerful hooks for developers to modify and extend the DQL language to their needs. DQL can either be written as a string or be generated using a powerful QueryBuilder object.
Your persistent objects (called entities in Doctrine 2) are not required to extend an abstract base class anymore. Doctrine 2 allows you to use Plain old PHP Objects.
The UnitOfWork is not an alibi-pattern as implemented in Doctrine 1. It is the most central pattern in Doctrine 2. Instead of calling save() or delete() methods on your Doctrine_Record instances you now pass objects to the data mapper object called EntityManager and it keeps track of all changes until you request a synchronisation between database and the current objects in memory. This process is very efficient and has consistent semantics. This is a significant improvement over Doctrine 1 in terms of performance and developer ease-of-use.
There are no code-generation steps from YAML to PHP involved in the library anymore. YAML, XML, PHP and Doc-Block Annotations are four first-class citizens for defining the metadata mapping between objects and database. A powerful caching layer allows Doctrine 2 to use runtime metadata without relying on code-generation.
A clean architecture and powerful algorithms make Doctrine 2 magnitudes faster than Doctrine 1.
Doctrine 2 supports an API that allows you to transform an arbitrary SQL statements into an object-structure. This feature is used by the Doctrine Query Language itself and is a first-class citizen of the library. It essentially allows you to make use of powerful vendor-specific features and complex SQL statements without having to cirumvent the ORM completely.
Inheritance is not akward anymore. There are now three different types of inheritance to choose from: Mapped Superclasses, Single-Table- and Joined-Table-Inheritance.
Many more features, just see the reference guide on what is possible with Doctrine 2.
Doctrine 2 now we feel this code is more stable and much more maintainable than Doctrine 1. The ORM itself has about 1000 tests where half of these are functional tests that successfully run against all the supported database vendors MySQL, SQLite, PostgreSQL, Oracle and MSSQL. The database access layer and common libraries come with an additional 400 tests.
Lazy load proxies always contain an instance of Doctrine’s EntityManager and all its dependencies. Therefore a var_dump() will possibly dump a very large recursive structure which is impossible to render and read. You have to use Doctrine\Common\Util\Debug::dump() to restrict the dumping to a human readable level. Additionally you should be aware that dumping the EntityManager to a Browser may take several minutes, and the Debug::dump() method just ignores any occurrences of it in Proxy instances.