In apps, entities often have references to other entities. For example, a User might have a "friends" collection of other Users and a "supervisor" User. This concept is known as _foreign keys_ in databases or _pointers_ in low-level software.
Strangely, Hive only supports saving collections of pointers in the form of a HiveList, not saving a single pointer.
I'd really like a HivePointer<T> type of some sort which points to another entity, possibly in another box. Maybe, the HivePointer could have a .resolve() method which resolves the reference.
Because it is so easy to implement such a class, I chose not to add it to Hive:
class HivePointer<T extends HiveObject> {
final Box foreignBox;
String _key;
HivePointer(this.foreignBox);
T get value => _key != null ? foreignBox.get(_key) : null;
set value(T obj) => _key = obj.key;
}
Now that I think about it, the adapter for the class above needs to be supported by the hive_generator to cast it automatically. This would be an argument for adding the HivePointer and its adapter.
Another thing I thought about: We could add a @HiveLink() annotation which could be added to any field of type HiveObject or List<HiveObject>.
@HiveType
class _Person {
String name;
@HiveLink(boxName: 'persons')
List<Person> friends;
@HiveLink(boxName: 'pets')
Pet dog;
}
The hive_generator would generate a class Person extends _Person which handles all the linking stuff without the user noticing. This generated class could also support optional auto-saving the object when a property is changed.
This is a major breaking change and would be Hive 2.0
Cool, looking forward to it 😊
I was looking for exactly that feature. Why is that a major breaking change?
Why is that a major breaking change?
Adding the HivePointer class is not a breaking change but I probably won't do that. Instead, I will require users to make their model classes private and let the hive_generator create a public subclass that handles the HivePointer and HiveList stuff. This will be a breaking change because every model class needs to be made private.
I'm not entirely sure I like that. I did go in the same direction with my data_classes package, where you create mutable classes and it generates an immutable one with copyWith methods, fancy constructor and the sorts – but in reality, I never used it for one simple reason: loss of control.
You want to add a different constructor for convenience? Not possible.
You want to use other packages, like json_serializable to generate methods for you? Nope, that doesn't work unless you're willing to litter your fetching and business logic with code like MutableUser.fromJson(…).toImmutable() or want to tinker with meta-annotations like e.g. @Annotation(JsonSerializable()), which I'm still not entirely convinced are possible at all.
Want to use multiple packages that use these "data class generation" functionalities? Not possible. People that use built_value for example, are equally cut off.
Generating the data classes I use just makes me as a developer feel like I lose a lot of control over classes that "should be mine". Implementing them as a requirement for Hive classes would be a deal-breaker for me. Let's just hope data classes become a language-level Dart feature sometime.
You want to add a different constructor for convenience? Not possible.
Why not? The generated class just needs to call your constructor with the same parameters.
You want to use other packages, like json_serializable to generate methods for you? Nope, that doesn't work
I also don't see why json_serializable would be a big problem...
Instead of
@HiveType()
@JsonSerializable()
class Person {
Person fromJson(Map<String, dynamic> json) {
return _$PersonFromJson(json);
}
}
You would need to write:
@HiveType()
@JsonSerializable()
class _Person {
Person fromJson(Map<String, dynamic> json) {
return Person._fromPerson(_$_PersonFromJson(json));
}
}
People that use built_value for example, are equally cut off.
I'm almost sure that build_value already does not work with Hive today. Personally I really dislike this package and I don't understand why people would use it. When Dart gets data classes, it will be obsolete anyway.
Generating the data classes I use just makes me as a developer feel like I lose a lot of control over classes that "should be mine"
I understand but the classes are managed by Hive and I don't really see any other way. The biggest reason why I want to make this change is that HiveLists need to be disposed before the object is garbage collected. Dart will probably get weak references in a few years (they are currently a stage 3 TC39 proposal in javascript) but until then, HiveLists need to be disposed manually. After this change, Hive could do the disposing automatically.
Most helpful comment
Another thing I thought about: We could add a
@HiveLink()annotation which could be added to any field of typeHiveObjectorList<HiveObject>.The
hive_generatorwould generate aclass Person extends _Personwhich handles all the linking stuff without the user noticing. This generated class could also support optional auto-saving the object when a property is changed.This is a major breaking change and would be Hive 2.0