0

I'm evaluating Spring Data's support for Couchbase, and have have run across the following issue. Consider the following pseudo-code example where I've two POJO classes, and a repository defined and instantiated for each:

public class Foo
{
    @Id
    private String  _id;

    @Version
    private Long    _rev;

    // .. Other data and members.
}

public class Bar
{
    @Id
    private String  _id;

    @Version
    private Long    _rev;

    // .. Other data and members.
}


//
// Repositories
//

@Repository
public interface FooRepository extends CrudRepository<Foo, String> {
}

@Repository
public interface BarRepository extends CrudRepository<Bar, String> {
}

Both repositories are utilizing the same Couchbase bucket. Next:

// Create a new Foo object and save it.
Foo f = new Foo( "id_1" );
fooRepository.save( f );

// Now, try fetching a Bar object using the ID of a Foo object (?)
Bar b = barRepository.findOne( "id_1" );

This results in a Bar object being returned, but not properly initialized - no exceptions are raised. The question, is why isn't an error indicated in this scenario? It seems like not much of a stretch to raise an exception when the requested type doesn't match the persisted type. Am I missing something?

FWIW, When I look at the raw documents in Couchbase via the admin console, I observe that each contains a "_class" property with presumably could be used to identify classes used to represent the data, and detect such mis-matches.

mikewied
  • 5,273
  • 1
  • 20
  • 32
Bukes
  • 3,668
  • 1
  • 18
  • 20
  • do you get more info in the logs? If its not able to parse it there should be something raised to you. .. since this is not an answer, can you open a DATACOUCH ticket on the tracker? – daschl Jul 16 '14 at 06:03
  • @moidaschl - Nothing shows up in the logs. I did step all the way through the code that implements this functionality. Interestingly, the code that handles deciding what type to use doesn't handle mismatches at all. See MappingCouchbaseConverter.read()/DefaultTypeMapper.readType() if you're interested. I will file a ticket for this. – Bukes Jul 16 '14 at 17:40

1 Answers1

0

The problem here is that a document (JSON serialized entity) is stored associated to the id (@Id field) on same bucket as other entities, this generates a kind of ambiguity, saving Entity1 with id 1, will overwrite Entity2 with id 1.

An application side solution would be to store entities with distinct keys, in the case of Entity1 with id 1 something like: 1-Entity1 as key.

Maybe you could solve the problem with an approach similar to this one:

public Entity1 {

    private static final String ENTITY_NAME = "ENTITY1";

    @Id
    private String key;

    public void setKey(String key) {
        this.key = key;
    }

    public String getKey(String key) {
        return this.key;
    }

    public void setId(String id) {
        this.key = ENTITY_NAME + ":" + id;
    }

    public String getId() {
        if (null == this.key) 
            return null;
        return this.key.substring(ENTITY_NAME.length()+1);
    }

}
Francisco Spaeth
  • 23,493
  • 7
  • 67
  • 106
  • There is no question that storing objects of dis-similar types in the same bucket can create ambiguity. My question is, why doesn't the CouchBase Crud repository package detect the scenario as an error when I ask a CrudRepository instance to return a Bar object, given an ID of a Foo object? Seems to me that verifying the type stored matches type being requested makes a lot of sense. – Bukes Aug 03 '14 at 21:12
  • I see. What I'm pointing is kind of root-cause for the issue pointed here. If you save, in your case `Foo` and `Bar`, with the same `@Id` the last one will override the first one what from my understanding shouldn't happen (its not intuitive). Considering that one shouldn't overwrite the other a check of entity class wouldn't make sense at read time. – Francisco Spaeth Aug 04 '14 at 07:41