Open valery-shinkevich opened 4 months ago
I found a good implementation of various UUID versions and made a small test of ordering of different types of UUIDv7. Add uuid7 and test (WIP)
Thank you for suggestion, we'll consider changing the default UUID provider to use UUIDv7 in the next feature release.
Currently you can use a custom provider for attributes annotated with @JmixGeneratedValue
if you define an appropriate EntityInitializer
bean in your project, for example:
package com.company.onboarding;
import io.jmix.core.EntityInitializer;
import io.jmix.core.JmixOrder;
import io.jmix.core.Metadata;
import io.jmix.core.UuidProvider;
import io.jmix.core.entity.EntityValues;
import io.jmix.core.entity.annotation.JmixGeneratedValue;
import io.jmix.core.metamodel.model.MetaClass;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import java.util.UUID;
@Component
public class MyGeneratedIdEntityInitializer implements EntityInitializer, Ordered {
private final Metadata metadata;
public MyGeneratedIdEntityInitializer(Metadata metadata) {
this.metadata = metadata;
}
@Override
public void initEntity(Object entity) {
MetaClass metaClass = metadata.getClass(entity);
metaClass.getProperties().stream()
.filter(property -> property.getRange().isDatatype()
&& property.getRange().asDatatype().getJavaClass().equals(UUID.class)
&& property.getAnnotations().get(JmixGeneratedValue.class.getName()) != null)
.forEach(property -> {
if (EntityValues.getValue(entity, property.getName()) == null) {
UUID uuid = UuidProvider.createUuid(); // use your UUID provider
EntityValues.setValue(entity, property.getName(), uuid);
}
});
}
@Override
public int getOrder() {
return JmixOrder.HIGHEST_PRECEDENCE - 10;
}
}
Pay attention to the order - it must be a lower number (higher precedence) than defined in the GeneratedIdEntityInitializer
bean of the framework.
Right now, Jmix uses a UuidProvider that generates randomly based UUIDs. This is sufficient for small applications, but for applications where there is a lot of data and UUID is used as primary keys, this causes poor index locality.
Various modifications of UUID generator have been used for a long time to solve this problem. They are all somewhat similar and use time-based UUID generation.
Not so long ago, new UUID formats were introduced, in particular UUIDv7. New UUID Formats - draft This is one of the solutions of poor index locality and already has many implementations for databases and programming languages. You can also read a lot of articles on this topic, for example: Goodbye integers. Hello UUIDv7! Спецификация уникальных идентификаторов UUIDv7 для ключей баз данных и распределенных систем по новому стандарту RFC9562
However, this solution is not suitable for all databases, as far as I know at the moment (I would be glad to be mistaken), MS SQL Server uses a slightly different byte order for storing GUIDs. Therefore, it would be nice to use the ability to set the generator in the application configuration.