Custom ID with ObjectBox

478

You've correctly assumed you can set relation.target (or relation.targetId) - it can point to an existing object, in which case ObjectBox won't try to create it. An adaptation of the following code should work for you:

final docTemplate = DocumentTemplateEntity(...)
final familyQuery = store.box<DocumentFamilyEntity>().query(DocumentFamilyEntity_.id.equals('unique ID of an existing family entity').build();

// and one of the following
docTemplate.family.target = familyQuery.findFirst(); 
// or
docTemplate.family.targetId = (familyQuery..limit = 1).findIds().firstOrNull; 
Share:
478
Teio07
Author by

Teio07

Updated on November 25, 2022

Comments

  • Teio07
    Teio07 over 1 year

    I'm using ObjectBox with Flutter and I'm having some trouble with the mandatory int id required by ObjectBox on each Entity.

    In my app I'm using custom ids using the uuid package and I'm mapping those Entity classes to my own Domain classes to make abstraction of the ObjectBox implementation.

    Those Entity classes have the mandatory int id required by ObjectBox that I defined as int obid annotated with @Id() and my own Domain id defined as String id with the @Unique() annotation.

    It just gives me a little bit more work when I need to get an Entity by id, but that's fine. The problem is when I need to add an Entity having a relation with another one, since my Domain classes don't have the obid when I convert from a Domain to an Entity class, the obid is omitted and defaults to 0, then ObjectBox tries to persist/create a new Entity and fail because of the @Unique() annotation of the id. I don't even want to create a new Entity for the relation. What I want is create an Entity and just put a reference to an already persisted Entity as the the relation.

    I think the way to do it is by setting relation.target or the relation.targetId but in my case, this won't work because it doesn't rely on my id.

    How can I make my own id work as a real id and not just a Unique constraint ?

    Here are some examples of those Entity and Domain classes :

    DocumentTemplateEntity :

    @Entity()
    class DocumentTemplateEntity {
      @Id()
      int obid = 0;
    
      @Unique()
      String id;
      String title;
      double leftMargin;
      double topMargin;
      double rightMargin;
      double bottomMargin;
      DateTime? insertedAt;
      DateTime? updatedAt;
      final family = ToOne<DocumentFamilyEntity>();
    
      DocumentTemplateEntity({
        required this.id,
        required this.title,
        required this.leftMargin,
        required this.topMargin,
        required this.rightMargin,
        required this.bottomMargin,
        this.insertedAt,
        this.updatedAt,
      });
    
      DocumentTemplate toDomain() => DocumentTemplate(
            id: UniqueId.fromUniqueString(id),
            title: DocumentTemplateTitle(title),
            leftMargin: leftMargin,
            topMargin: topMargin,
            rightMargin: rightMargin,
            bottomMargin: bottomMargin,
            insertedAt: insertedAt,
            updatedAt: updatedAt,
            family: family.target!.toDomain(),
          );
    
      factory DocumentTemplateEntity.fromDomain(DocumentTemplate template) =>
          DocumentTemplateEntity(
            id: template.id.getOrCrash(),
            title: template.title.getOrCrash(),
            leftMargin: template.leftMargin,
            topMargin: template.topMargin,
            rightMargin: template.rightMargin,
            bottomMargin: template.bottomMargin,
            insertedAt: template.insertedAt,
            updatedAt: template.updatedAt,
          )..family.target = DocumentFamilyEntity.fromDomain(template.family);
    }
    

    DocumentFamilyEntity :

    @Entity()
    class DocumentFamilyEntity {
      @Id()
      int obid = 0;
    
      @Unique()
      String id;
      String title;
      int sortOrder;
      DateTime? insertedAt;
      DateTime? updatedAt;
    
      DocumentFamilyEntity({
        required this.id,
        required this.title,
        required this.sortOrder,
        this.insertedAt,
        this.updatedAt,
      });
    
      DocumentFamily toDomain() => DocumentFamily(
            id: UniqueId.fromUniqueString(id),
            title: title,
            sortOrder: sortOrder,
            insertedAt: insertedAt,
            updatedAt: updatedAt,
          );
    
      factory DocumentFamilyEntity.fromDomain(DocumentFamily family) =>
          DocumentFamilyEntity(
            id: family.id.getOrCrash(),
            title: family.title,
            sortOrder: family.sortOrder,
            insertedAt: family.insertedAt,
            updatedAt: family.updatedAt,
          );
    }
    

    DocumentTemplate (Domain) :

    @freezed
    class DocumentTemplate with _$DocumentTemplate {
      factory DocumentTemplate({
        required UniqueId id,
        required DocumentTemplateTitle title,
        required double leftMargin,
        required double topMargin,
        required double rightMargin,
        required double bottomMargin,
        required DocumentFamily family,
        DateTime? insertedAt,
        DateTime? updatedAt,
      }) = _DocumentTemplate;
    
      factory DocumentTemplate.initial() => DocumentTemplate(
            id: UniqueId(),
            title: DocumentTemplateTitle(''),
            leftMargin: 1.0,
            topMargin: 1.0,
            rightMargin: 1.0,
            bottomMargin: 1.0,
            family: DocumentFamily.initial(),
          );
    }
    

    DocumentFamily (Domain) :

    @freezed
    class DocumentFamily with _$DocumentFamily {
      factory DocumentFamily({
        required UniqueId id,
        required int sortOrder,
        required String title,
        DateTime? insertedAt,
        DateTime? updatedAt,
      }) = _DocumentFamily;
    
      factory DocumentFamily.initial() => DocumentFamily(
            id: UniqueId(),
            sortOrder: 0,
            title: '',
          );
    }
    
  • Teio07
    Teio07 almost 3 years
    Yes, it seems like the only solution for now but I found out that with ObjectBox Java, you had the option of adding a parameter to the @Unique() annotation (something like @Unique(onConflict = ConflictStrategy.REPLACE) ) that would replace the Entity in the case it already existed. As referenced here : github.com/objectbox/objectbox-java/issues/… I guess it would solve my problem and make the @Unique() annotation behave more like a real ID. Will this feature come to ObjectBox Dart too ? Thanks for the help !
  • vaind
    vaind almost 3 years
    I'm not aware of anyone working on this at the moment. If that's something you'd like to use, you can create a feature request (issue) on github for objectbox-dart. Even better, you can contribute the change :)
  • Tanuki
    Tanuki about 2 years
    Hello! I saw you're a objectbox's collaborator, what about a ConflictStrategy.UPDATE @vaind ? github.com/objectbox/objectbox-dart/issues/378