简体   繁体   中英

Should a repository always return the same reference in memory when querying for the same ID?

In many blogs or articles one reads the following statement about the repository

You should think of a repository as a collection of domain objects in memory

Now i am asking myself what should happen when i query the repository for the same Id twice.

Entity a = theRepo.GetById(1);
Entity b = theRepo.GetById(1);

assertTrue( a == b ); // Do they share the same reference ?
assertTrue( a.equals( b ) ); // This should always be true
  • Should the repository always return the same reference in memory ?
  • Should the repository return a new instance of the entity but with equal state?

I don't think you can assume that a == b .

Consider the situation where you got instance a , and started to modify it, not yet saving it back to your database. If another thread requests the same entity and puts it in variable b , it should get a new one reflecting the data in the database, not a dirty one that another thread is modifying and hasn't yet (and possibly never will) save.

On the other hand, assuming that a or b has not been subsequently modified after it has been retrieved from the same repository, it should be safe to assume that a.equals(b) , also assuming that the equals() method has been implemented correctly for the entity.

In my opinion, your problem boils down to the lifespan of the repository. Repositories are transient (ideally) and also, sometimes, they live inside another class called "Unit of Work" which is transient as well.

I don't think this is a DDD issue, but more of an Infrastructure issue.

Given an entity type, a repository is a collection of instances of a the given entity type.

A repository doesn't create instances of the entity. It is just a collection (in the sense of a "set") of instances that you created before. Then you add those instances to the repository (set of instances). And you can retrieve those instances.

A set doesn't duplicate elements. Given an id (eg id=1), the set will just have one instance with id=1, and that instance is the one you retrieve when you call "theRepo.GetById(1)".

So:

Entity a = theRepo.GetById(1);

Entity b = theRepo.GetById(1);

Should the repository always return the same reference in memory ?

See UPDATE 3.

Should the repository return a new instance of the entity but with equal state?

No. The repository should return the instance that you added before. The repository shouldn't create new instances.

Anyway, in order to check whether two instances are the same, you shouldn't compare the references, you should compare their ids.

You are mixing concepts. A repository is just a collection (set) of instances. Instances are created by factories (or by constructor methods of the entity).

See IDDD book by Vaughn Vernon ("Collection-Oriented Repositories" section in Chapter 12).

Hope it helps.

UPDATE:

When I say "...Repository is a set of instances..." I mean it mimics a set. My fault not expressing it well. Regarding to update an instance of the repository, such operation doesn't exist, since when you retrieve an instance and modify it, the changes are made in the instance of the repository, you don't have to re-save the instance. The peristence mechanism implemeting the repository must have capabilities to ensure this behaviour. See Chapter 12 of the Implementing DDD book by Vaugn Vernon.

UPDATE 2:

I want to clarify that what I say here is my understanding after reading Vaughn Vernon book IDDD, and also another book (Domain Driven Design in PHP, by Carlos Buenosvinos). I'm not trying to be misleading at all.

UPDATE 3:

I asked Vaughn Vernon the following question:

Regarding collection-oriented repository, I have a question: If I do Foo aFoo=fooRepository.getById(1); Foo anotherFoo=fooRepository.getById(1); Foo aFoo=fooRepository.getById(1); Foo anotherFoo=fooRepository.getById(1); then is it guaranteed that both references are the same (aFoo==anotherFoo)?

And he answered the following:

That depends on the backing persistence mechanism, such as Hibernate/JPA. It seems it should if you are using the same session in both reads and both reads have the same transactional scope, but check with your ORM.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM