Closed aminelaadhari closed 8 years ago
I think we did this intentionally because we did not want to insert those default values into SQLite (SQLite can have null values in any column, regardless of type). Any insert would write those values to the database, so if you want to have those default values in Java, we want you to commit to holding them in the database as well.
I think this is misleading because in java when you define something like this in the Spec: boolean isDeleted; by default it is false and not null.
in generates this: public Boolean isDeleted() { return get(IS_DELETED); }
and you get a null value. So something is not coherent between the spec and the generated code.
Indeed, all column values in SquiDB (with the exception of the row id) are represented as objects (e.g. java.lang.Long
instead of primitive long
), not primitives, so they have a default value of null and/or can be assigned a null value. As @jdkoren suggests, this behavior is meant to mimic SQLite, where the default value of a column that does not otherwise specify a default is null.
To specify a default value for any column, you can annotate the field with e.g. @ColumnSpec(defaultValue="0L")
. However, it is always still possible to set any value to null at runtime. To perform a null check before reading the value, you can do this:
if (model.containsNonNullValue(MyModel.IS_DELETED)) {
...
}
The spec is just meant to be a shorthand for specifying a table schema -- it's not a "real" Java object and shouldn't really be thought of as one. In fact, the fields in spec itself aren't even used at runtime -- they're only there for the code generator to parse. It's a core architectural detail of SquiDB that the values stored in model objects are objects, not primitives, and this is unlikely to change.
Maybe someday we'll add additional annotations and validation for things like NOT NULL
constraints that could make use of primitives, but we can't commit to any specific timeline for such a change.
Ok got it. Thank you both.
I don't want to add this checks everywhere:
if (model.containsNonNullValue(MyModel.IS_DELETED)) { ... }
I would like to use something more generic like Optional or a plugin which generates hasIsDeleted method.
what is the best option here ? any thoughts? Thanks
So many options! You can pick your favorite:
@ModelMethod
to add a hasIsDeleted()
method to the generated classTableModelFieldSpecPlugin
and provide custom PropertyGenerator
objects for primitive fields that were annotated with some custom annotation. TableModelFieldSpecPlugin
makes this possible by overriding methods like getLongPropertyGenerator()
or getIntegerPropertyGenerator()
. Then you'd declare the plugin as having high
priority so that it takes precedence over SquiDB's default field handling. The main caveat is that under the hood the value is still stored as a wrapped object, but if you commit to using only the generated getters and setters (instead of the generic get()/set()
by Property) for such fields it could be mostly safe.That last option is kind of hard to describe, so if it sounds good to you but you need some more guidance, let me know and I'll put up a gist somewhere. Obviously using primitives isn't something that's built into the core of SquiDB by default, so it does come with risks as we've never tried it ourselves, but it might serve your use case best.
Great thank you. I like how much flexible is Squidb! Feel free to close the issue. Thanks a lot !
Glad to help!
Actually primitive members don't have any default value and cause a NullPointerException when you try to read them. I think they should have the default values defined by java by default: http://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html