18. Partial Objects

Note

ノート

Creating Partial Objects through DQL is deprecated and will be removed in the future, use data transfer object support in DQL instead. (Details)

DQL による部分オブジェクトの作成は非推奨であり、今後削除される予定です。代わりに、DQL のデータ転送オブジェクト サポートを使用してください。 (詳細)

A partial object is an object whose state is not fully initialized after being reconstituted from the database and that is disconnected from the rest of its data. The following section will describe why partial objects are problematic and what the approach of Doctrine2 to this problem is.

部分オブジェクトとは、データベースから再構成された後、状態が完全に初期化されておらず、残りのデータから切断されているオブジェクトです。次のセクションでは、部分オブジェクトが問題となる理由と、この問題に対する Doctrine2 のアプローチについて説明します。

Note

ノート

The partial object problem in general does not apply to methods or queries where you do not retrieve the query result as objects. Examples are: Query#getArrayResult(), Query#getScalarResult(), Query#getSingleScalarResult(), etc.

一般に、部分オブジェクトの問題は、クエリ結果をオブジェクトとして取得しないメソッドまたはクエリには適用されません。例: Query#getArrayResult()、Query#getScalarResult()、Query#getSingleScalarResult()など。

Warning

警告

Use of partial objects is tricky. Fields that are not retrieved from the database will not be updated by the UnitOfWork even if they get changed in your objects. You can only promote a partial object to a fully-loaded object by calling EntityManager#refresh() or a DQL query with the refresh flag.

部分オブジェクトの使用には注意が必要です。データベースから取得されないフィールドは、オブジェクトで変更されても、UnitOfWork によって更新されません。 EntityManager#refresh() を呼び出すか、更新フラグを指定して DQL クエリを呼び出すことによってのみ、部分的なオブジェクトを完全に読み込まれたオブジェクトに昇格させることができます。

18.1. What is the problem?

In short, partial objects are problematic because they are usually objects with broken invariants. As such, code that uses these partial objects tends to be very fragile and either needs to “know” which fields or methods can be safely accessed or add checks around every field access or method invocation. The same holds true for the internals, i.e. the method implementations, of such objects. You usually simply assume the state you need in the method is available, after all you properly constructed this object before you pushed it into the database, right? These blind assumptions can quickly lead to null reference errors when working with such partial objects.

要するに、部分オブジェクトは通常、壊れた不変条件を持つオブジェクトであるため、問題があります。そのため、これらの部分オブジェクトを使用するコードは非常に脆弱になる傾向があり、どのフィールドまたはメソッドに安全にアクセスできるかを「知る」か、すべてのフィールド アクセスまたはメソッド呼び出しにチェックを追加する必要があります。同じことが、そのようなオブジェクトの内部、つまりメソッドの実装にも当てはまります。通常、このオブジェクトをデータベースにプッシュする前に、このオブジェクトを適切に構築した後は、メソッドで必要な状態が利用可能であると単純に想定しますよね?これらの盲目的な仮定は、そのような部分オブジェクトを操作するときに、すぐに null 参照エラーにつながる可能性があります。

It gets worse with the scenario of an optional association (0..1 to 1). When the associated field is NULL, you don’t know whether this object does not have an associated object or whether it was simply not loaded when the owning object was loaded from the database.

オプションの関連付け (0..1 to1) のシナリオではさらに悪化します。関連フィールドが NULL の場合、このオブジェクトに関連オブジェクトがないのか、所有オブジェクトがデータベースからロードされたときに単にロードされなかったのかはわかりません。

These are reasons why many ORMs do not allow partial objects at all and instead you always have to load an object with all its fields (associations being proxied). One secure way to allow partial objects is if the programming language/platform allows the ORM tool to hook deeply into the object and instrument it in such a way that individual fields (not only associations) can be loaded lazily on first access. This is possible in Java, for example, through bytecode instrumentation. In PHP though this is not possible, so there is no way to have “secure” partial objects in an ORM with transparent persistence.

これらが、多くの ORM が部分的なオブジェクトをまったく許可しない理由であり、その代わりに常にオブジェクトをそのすべてのフィールド (プロキシされている関連付け) と共にロードする必要があります。部分オブジェクトを許可する安全な方法の 1 つは、プログラミング言語/プラットフォームが ORM ツールをオブジェクトに深くフックし、個々のフィールド (関連付けだけでなく) を最初のアクセスで遅延ロードできるようにすることです。これは、Java ではバイトコード インストルメンテーションなどによって可能です。 PHP ではこれは不可能ですが、透過的な永続性を持つ ORM で「安全な」部分オブジェクトを保持する方法はありません。

Doctrine, by default, does not allow partial objects. That means, any query that only selects partial object data and wants to retrieve the result as objects (i.e. Query#getResult()) will raise an exception telling you that partial objects are dangerous. If you want to force a query to return you partial objects, possibly as a performance tweak, you can use the partial keyword as follows:

デフォルトでは、Doctrine は部分オブジェクトを許可しません。つまり、部分的なオブジェクト データのみを選択し、結果をオブジェクトとして取得するクエリ (つまり、Query#getResult()) は、部分的なオブジェクトが危険であることを示す例外を発生させます。おそらくパフォーマンスの微調整として、次のように partial キーワードを使用できます。

<?php
$q = $em->createQuery("select partial u.{id,name} from MyApp\Domain\User u");

You can also get a partial reference instead of a proxy reference by calling:

次の呼び出しにより、プロキシ参照の代わりに部分参照を取得することもできます。

<?php
$reference = $em->getPartialReference('MyApp\Domain\User', 1);

Partial references are objects with only the identifiers set as they are passed to the second argument of the getPartialReference() method. All other fields are null.

部分参照は、getPartialReference() メソッドの 2 番目の引数に渡されるときに識別子のみが設定されたオブジェクトです。他のすべてのフィールドは null です。

18.2. When should I force partial objects?

Mainly for optimization purposes, but be careful of premature optimization as partial objects lead to potentially more fragile code.

主に最適化を目的としていますが、部分的なオブジェクトがコードの脆弱性を高める可能性があるため、時期尚早の最適化には注意してください。

Table Of Contents

Previous topic

17. Change Tracking Policies

17. 変更追跡ポリシー

Next topic

19. Annotations Reference

19. 注釈リファレンス

This Page

Fork me on GitHub