1
0
Fork 0
mirror of synced 2025-03-28 19:03:50 +03:00

Merge branch 'DDC-692'

This commit is contained in:
Benjamin Eberlei 2011-03-29 20:17:56 +02:00
commit e9c4f612cf
11 changed files with 106 additions and 5 deletions

View file

@ -88,6 +88,7 @@
<xs:attribute name="repository-class" type="xs:string"/> <xs:attribute name="repository-class" type="xs:string"/>
<xs:attribute name="inheritance-type" type="orm:inheritance-type"/> <xs:attribute name="inheritance-type" type="orm:inheritance-type"/>
<xs:attribute name="change-tracking-policy" type="orm:change-tracking-policy" /> <xs:attribute name="change-tracking-policy" type="orm:change-tracking-policy" />
<xs:attribute name="read-only" type="xs:boolean" default="false" />
</xs:complexType> </xs:complexType>
<xs:complexType name="mapped-superclass" > <xs:complexType name="mapped-superclass" >

View file

@ -334,6 +334,10 @@ class ClassMetadata extends ClassMetadataInfo
$serialized[] = 'namedQueries'; $serialized[] = 'namedQueries';
} }
if ($this->isReadOnly) {
$serialized[] = 'isReadOnly';
}
return $serialized; return $serialized;
} }

View file

@ -484,6 +484,17 @@ class ClassMetadataInfo implements ClassMetadata
*/ */
public $reflClass; public $reflClass;
/**
* Is this entity marked as "read-only"?
*
* That means it is never considered for change-tracking in the UnitOfWork. It is a very helpful performance
* optimization for entities that are immutable, either in your domain or through the relation database
* (coming from a view, or a history table for example).
*
* @var bool
*/
public $isReadOnly = false;
/** /**
* Initializes a new ClassMetadata instance that will hold the object-relational mapping * Initializes a new ClassMetadata instance that will hold the object-relational mapping
* metadata of the class with the given name. * metadata of the class with the given name.
@ -1818,4 +1829,14 @@ class ClassMetadataInfo implements ClassMetadata
{ {
$this->versionField = $versionField; $this->versionField = $versionField;
} }
/**
* Mark this class as read only, no change tracking is applied to it.
*
* @return void
*/
public function markReadOnly()
{
$this->isReadOnly = true;
}
} }

View file

@ -132,6 +132,10 @@ class AnnotationDriver implements Driver
if (isset($classAnnotations['Doctrine\ORM\Mapping\Entity'])) { if (isset($classAnnotations['Doctrine\ORM\Mapping\Entity'])) {
$entityAnnot = $classAnnotations['Doctrine\ORM\Mapping\Entity']; $entityAnnot = $classAnnotations['Doctrine\ORM\Mapping\Entity'];
$metadata->setCustomRepositoryClass($entityAnnot->repositoryClass); $metadata->setCustomRepositoryClass($entityAnnot->repositoryClass);
if ($entityAnnot->readOnly) {
$metadata->markReadOnly();
}
} else if (isset($classAnnotations['Doctrine\ORM\Mapping\MappedSuperclass'])) { } else if (isset($classAnnotations['Doctrine\ORM\Mapping\MappedSuperclass'])) {
$metadata->isMappedSuperclass = true; $metadata->isMappedSuperclass = true;
} else { } else {

View file

@ -1,7 +1,5 @@
<?php <?php
/* /*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@ -27,6 +25,7 @@ use Doctrine\Common\Annotations\Annotation;
final class Entity extends Annotation { final class Entity extends Annotation {
public $repositoryClass; public $repositoryClass;
public $readOnly = false;
} }
final class MappedSuperclass extends Annotation {} final class MappedSuperclass extends Annotation {}
final class InheritanceType extends Annotation {} final class InheritanceType extends Annotation {}

View file

@ -55,6 +55,9 @@ class XmlDriver extends AbstractFileDriver
$metadata->setCustomRepositoryClass( $metadata->setCustomRepositoryClass(
isset($xmlRoot['repository-class']) ? (string)$xmlRoot['repository-class'] : null isset($xmlRoot['repository-class']) ? (string)$xmlRoot['repository-class'] : null
); );
if (isset($xmlRoot['read-only']) && $xmlRoot['read-only'] == "true") {
$metadata->markReadOnly();
}
} else if ($xmlRoot->getName() == 'mapped-superclass') { } else if ($xmlRoot->getName() == 'mapped-superclass') {
$metadata->isMappedSuperclass = true; $metadata->isMappedSuperclass = true;
} else { } else {

View file

@ -49,6 +49,9 @@ class YamlDriver extends AbstractFileDriver
$metadata->setCustomRepositoryClass( $metadata->setCustomRepositoryClass(
isset($element['repositoryClass']) ? $element['repositoryClass'] : null isset($element['repositoryClass']) ? $element['repositoryClass'] : null
); );
if (isset($element['readOnly']) && $element['readOnly'] == true) {
$metadata->markReadOnly();
}
} else if ($element['type'] == 'mappedSuperclass') { } else if ($element['type'] == 'mappedSuperclass') {
$metadata->isMappedSuperclass = true; $metadata->isMappedSuperclass = true;
} else { } else {

View file

@ -514,9 +514,9 @@ class UnitOfWork implements PropertyChangedListener
$class = $this->em->getClassMetadata($className); $class = $this->em->getClassMetadata($className);
// Skip class if instances are read-only // Skip class if instances are read-only
//if ($class->isReadOnly) { if ($class->isReadOnly) {
// continue; continue;
//} }
// If change tracking is explicit or happens through notification, then only compute // If change tracking is explicit or happens through notification, then only compute
// changes on entities of that type that are explicitly marked for synchronization. // changes on entities of that type that are explicitly marked for synchronization.

View file

@ -59,6 +59,7 @@ class AllTests
$suite->addTestSuite('Doctrine\Tests\ORM\Functional\PostgreSQLIdentityStrategyTest'); $suite->addTestSuite('Doctrine\Tests\ORM\Functional\PostgreSQLIdentityStrategyTest');
$suite->addTestSuite('Doctrine\Tests\ORM\Functional\ExtraLazyCollectionTest'); $suite->addTestSuite('Doctrine\Tests\ORM\Functional\ExtraLazyCollectionTest');
$suite->addTestSuite('Doctrine\Tests\ORM\Functional\ClearEventTest'); $suite->addTestSuite('Doctrine\Tests\ORM\Functional\ClearEventTest');
$suite->addTestSuite('Doctrine\Tests\ORM\Functional\ReadOnlyTest');
$suite->addTest(Locking\AllTests::suite()); $suite->addTest(Locking\AllTests::suite());
$suite->addTest(Ticket\AllTests::suite()); $suite->addTest(Ticket\AllTests::suite());

View file

@ -0,0 +1,61 @@
<?php
namespace Doctrine\Tests\ORM\Functional;
require_once __DIR__ . '/../../TestInit.php';
/**
* Functional Query tests.
*
* @group DDC-692
*/
class ReadOnlyTest extends \Doctrine\Tests\OrmFunctionalTestCase
{
protected function setUp()
{
parent::setUp();
$this->_schemaTool->createSchema(array(
$this->_em->getClassMetadata('Doctrine\Tests\ORM\Functional\ReadOnlyEntity'),
));
}
public function testReadOnlyEntityNeverChangeTracked()
{
$readOnly = new ReadOnlyEntity("Test1", 1234);
$this->_em->persist($readOnly);
$this->_em->flush();
$readOnly->name = "Test2";
$readOnly->number = 4321;
$this->_em->flush();
$this->_em->clear();
$dbReadOnly = $this->_em->find('Doctrine\Tests\ORM\Functional\ReadOnlyEntity', $readOnly->id);
$this->assertEquals("Test1", $dbReadOnly->name);
$this->assertEquals(1234, $dbReadOnly->number);
}
}
/**
* @Entity(readOnly=true)
*/
class ReadOnlyEntity
{
/**
* @Id @GeneratedValue @Column(type="integer")
* @var int
*/
public $id;
/** @column(type="string") */
public $name;
/** @Column(type="integer") */
public $number;
public function __construct($name, $number)
{
$this->name = $name;
$this->number = $number;
}
}

View file

@ -30,6 +30,8 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase
$cm->setCustomRepositoryClass("UserRepository"); $cm->setCustomRepositoryClass("UserRepository");
$cm->setDiscriminatorColumn(array('name' => 'disc', 'type' => 'integer')); $cm->setDiscriminatorColumn(array('name' => 'disc', 'type' => 'integer'));
$cm->mapOneToOne(array('fieldName' => 'phonenumbers', 'targetEntity' => 'Bar', 'mappedBy' => 'foo')); $cm->mapOneToOne(array('fieldName' => 'phonenumbers', 'targetEntity' => 'Bar', 'mappedBy' => 'foo'));
$cm->markReadOnly();
$cm->addNamedQuery(array('name' => 'dql', 'query' => 'foo'));
$this->assertEquals(1, count($cm->associationMappings)); $this->assertEquals(1, count($cm->associationMappings));
$serialized = serialize($cm); $serialized = serialize($cm);
@ -51,6 +53,8 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase
$this->assertTrue($oneOneMapping['fetch'] == ClassMetadata::FETCH_LAZY); $this->assertTrue($oneOneMapping['fetch'] == ClassMetadata::FETCH_LAZY);
$this->assertEquals('phonenumbers', $oneOneMapping['fieldName']); $this->assertEquals('phonenumbers', $oneOneMapping['fieldName']);
$this->assertEquals('Doctrine\Tests\Models\CMS\Bar', $oneOneMapping['targetEntity']); $this->assertEquals('Doctrine\Tests\Models\CMS\Bar', $oneOneMapping['targetEntity']);
$this->assertTrue($cm->isReadOnly);
$this->assertEquals(array('dql' => 'foo'), $cm->namedQueries);
} }
public function testFieldIsNullable() public function testFieldIsNullable()