getNextIdForColumn retourne une valeur incorrecte

Bonjour,
je travaille sur un objet sans vraie clé fonctionnelle. J’ai décidé d’en fabriquer une comme ceci :

@Override
public void preCreate() {
	this.getField("RCMRequestId").setValue("REQUEST-" + this.getGrant().getNextIdForColumn(this.getTable(),"row_id"));
}

La méthode getNextIdForColumn devrait donc être égale au row_id de l’élément or j’obtiens ceci :
image

Il semblerai que le Next Id soit impacté par les suppressions réalisées sur les objects.
Ceci est problématique car il est arrivé que le getNextIdForColumn me retourne parfois un indice déjà utilisé. Résultat : impossible de créer les objets sans action manuelle pour changer l’indice.

Cordialement

[Platform]
Status=OK
Version=4.0.P24
BuiltOn=2020-04-24 22:35 (revision 3fe76ae912e69f249470c97013574fce47b7e1d2)
Encoding=UTF-8
EndpointIP=21.0.9.3
EndpointURL=http://905ccbc17725:8080
TimeZone=Europe/Paris
SystemDate=2020-05-27 09:45:19

Bonjour,

Aucune anomalie, cette méthode réalise un auto-incrément de la colonne : soit par sequence oracle ou postgresql, soit dans la table m_rowid. A chaque fois qu’elle est appelé l’id s’incrémente, donc il est normal que votre code n’aligne jamais le row_id interne et votre champ.

Dans la démo, le numéro de commande est le row_id sans aucun code :
default value = [ROWID]

Le preCreate ne réserve en aucun cas un row_id jusqu’au create en base si 2 utilisateurs le font en même temps sauf dans le cas particulier oracle et postgresql qui utilisent des séquences auto-commitées, donc appeler cette méthode incrémente la séquence, et le create interne Simplicité le refera une 2eme fois.

De plus suite à une suppression du dernier tuple, il y a un risque de générer 2 fois le même request id par votre mécanisme.

Autre point, votre clé est un string et non un entier, le “order by” va ordonner comme suit : REQUEST-1 REQUEST-10 REQUEST-2… il faudrait padder avec des 000 pour avoir un tri correct : REQUEST-001 REQUEST-002 REQUEST-010. Mais autant utiliser un number, car le “REQUEST-” fixe ne porte aucune information.

Si vous voulez un max+1 “maison” sans incrémenter une séquence, il faut juste consulter la valeur max de votre colonne pour valoriser un champ calculé.

Exemple de facture numéroté par année INVOICE-YYYY-NNNNN :

private String myNextId() {
  String year = Tool.getCurrentyear(); // 2020
  String max = getGrant().simpleQuery(
    "select max(invoice_num) from my_invoice where invoice_num like 'INVOICE-"+year+"-%");
  int n = max.length()>0 ? Integer.parseInt(max.substring(13)) : 0;
  return "INVOICE-" + year + "-" + Tool.lpadString(String.valueOf(n+1), '0', 5);
}

A appeler dans l’initCreate, initCopy et preCreate pour valoriser un champ clé “invoice_num”.

Il y a aussi les méthodes getMaxIdWhere pour consulter simplement la valeur “max” d’une colonne sans écrire de SQL.

.

Personnellement je ne récupère jamais de valeur dans les initXxx mais je laisse vide ou j’affiche un texte “Calculé automatiquement” puis je valorise ce champ dans le preValidate ou, mieux, le preCreate (en ayant positionné une valeur par défaut qui passe le validate dans le preValidate).

Ce pattern a l’avantage de ne pas afficher sur le formulaire de création une valeur qui ne sera pas forcément la valeur physiquement créée (ex:en cas de 2 users en création en //) ni de “griller” des valeurs de séquence pour rien (ex: en cas d’erreur de validate sur d’autres attributs)

1 Like