Multi datasources

Question de Benjamin :

Est-il possible de connecter Simplicité à une autre base (2 connecteurs JDBC), de façon à pouvoir créer avec Simplicité une IHM de CRUD d’une table relationnelle sans la changer de base?

Oui, il faut créer plusieurs datasource dans le contexte de l’application, et dans la définition de l’objet il faut le spécifier en plus du nom de la table : MY_OTHER_DATASOURCE;[<schema name>.]<table name>

https://www.simplicite.io/resources/documentation/99-misc/datasources-howto.md

Par contre Simplicité ne sait pas faire des jointures SQL sur des objets dans différents data-sources.
Nous n’avons pas préférer faire des jointures applicatives en java (pas d’indexation, chargement mémoire des tables…)

Dans ce cas, si on veut faire des jointures SQL inter-db, il faut ramener logiquement la table dans son SGBD via un mécanisme du SGBD (ex via DBLINK Oracle, je ne crois pas que Mysql ait ce genre de mécanisme, faut consulter son DBA préféré).

Si les schémas sont dans la même base, on peut faire des jointures du moment que le compte qui se connecte a les droits de lecture (en spécifiant le schémas en plus de la table dans la définition de l’objet <schema name>.<table name>).

Ensuite pour la paramétrage des champs l’objet, se pose la question de la clé fonctionnelle, du row_id et du timestamp.

  • pas de row_id numérique : on peut utiliser un autre champ clé
  • pas de timestamp : on ne peut plus utiliser les mécanismes de timestamp (sauf si présence des colonnes created_dt, created_by, updated_dt, updated_by), c’est le dernier qui met à jour qui gagne.

j’ai déclaré un paramètre système :
BLUEWAY_DATASOURCE
{
“driver”: “xxx”,
“username”: “xxxx”,
“password”: “xxxx”,
“url”: “postgresql://xxxx”
}

j’ai ensuite créé un objet métier en référençant la table :
BLUEWAY_DATASOURCE;[dev_demat.]gda_transcocdr

cette table n’a pas de colonne row_id mais une colonne id, que j’ai déclaré comme attribut et clé fonctionnelle.

j’ai des erreurs dans les logs : 2017-12-18 11:24:38,761 ERROR [com.simplicite.util.engine.ObjectManager] SIMPLICITE|http://dev-sim:10098/demat|/demat|ECOREDB001|system|com.simplicite.util.engine.ObjectManager|query||Erreur SQL requête: BLUEWAY_DATASOURCE: select t.row_id, t.id, t.code_cdr, t.libelle, t.actif from [dev_demat.]gda_transcocdr t where (1=1) order by t.row_id asc
java.lang.NullPointerException
2017-12-18 11:24:28,753 ERROR [com.simplicite.util.engine.ObjectManager] SIMPLICITE|http://dev-sim:10098/demat|/demat|ECOREDB001|system|com.simplicite.util.engine.ObjectManager|query||Erreur SQL requête: BLUEWAY_DATASOURCE: select count(t.row_id) from [dev_demat.]gda_transcocdr t where (1=1)
java.lang.NullPointerException

comment faire pour que le row_id ne soit pas attendu dans la table ?

Déjà il ne faut pas metre de crochets dans la table (les crochet c’est une convention usuelle pour dire qu’on peut ajouter de manière optionnelle un schema), les valeurs possibles donc donc:

mondatasource;matable
ou
mondatasource;monschema.matable

Ensuite quand la table sur laquelle on pointe n’a pas de colonne row_id il faut déclarer un attribut ID specifique ça se fait là:

j’ai changé la déclaration de la table et j’ai ajouté le nom logique de l’attribut identifiant et j’ai toujours une erreur.

2017-12-18 12:23:50,433 ERROR [com.simplicite.util.engine.ObjectManager] SIMPLICITE|http://dev-sim:10098/demat|/demat|ECOREDB001|system|com.simplicite.util.engine.ObjectManager|query||Erreur SQL requête: BLUEWAY_DATASOURCE: select t.id, t.code_cdr, t.libelle, t.actif from dev_demat.gda_transcocdr t where (1=1) order by t.id asc
java.lang.NullPointerException
2017-12-18 12:23:40,427 ERROR [com.simplicite.util.engine.ObjectManager] SIMPLICITE|http://dev-sim:10098/demat|/demat|ECOREDB001|system|com.simplicite.util.engine.ObjectManager|query||Erreur SQL requête: BLUEWAY_DATASOURCE: select count(t.id) from dev_demat.gda_transcocdr t where (1=1)
java.lang.NullPointerException

j’ai l’impression que la déclaration de mon paramètre système ne lui plait pas :
{
“driver”: “org.postgresql.Driver”,
“username”: “xxxx”,
“password”: “xxxx”,
“url”: “postgresql://xxxx”
}

Je trouve le No de port 3306 douteux s’agissant visiblement f’une base PostgreSQL mais bon c’est peut être normal.

Sinon il faut déclarer l’objet comme non timestampé s’il n’y a pas les colonnes created/updated_by/dt dans la table.

J’ai fait le test avec ce datasource PostgreSQL:

En base j’ai la table test:

test=> select * from test;
  id   |   label
-------+-----------
 ID001 | Label 001
 ID002 | Label 002
 ID003 | Label 003
(3 rows)

J’ai paramétré cet objet métier:

Avec le champ “ID” défini comme ça:

et juste un attribut métier “Libellé” définit comme ça:

Et ça marche:

le port est bon, je me connecte sans pb à la base avec mySql Workbench.

j’ai fait la même chose et ça ne fonctionne pas.

je vais voir en interne s’il n’y a pas un pb d’interrogation de la base de données distante par mon instance simplicité.

Si c’est une base MySQL il faut configurer un datasource MySQL, pas un datasource PostgreSQL

On a ajouté un exemple MySQL dans la doc: https://www.simplicite.io/resources/documentation/99-misc/datasources-howto.md

j’ai un gros doute sur le type de base ( je ne connais pas la base), mais en plus, il y avait un pb de firewall.

je poursuis mes recherches.
merci pour l’exemple MySQL

c’est bon ça fonctionne. Merci

Bonjour,

la connexion fonctionne, j’arrive à faire un update mais pas ce create :

  • le bouton créer ouvre bien le formulaire en création mais le hook initCreate n’est pas exécuté.
  • la fonction obj.getGrant().getNextIdForColumn(obj.getTable(), number.getColumn()) plante avec le message suivant : SELECT command denied to user ‘demat’@‘dev-sim.cr-bretagne.fr’ for table ‘gda_transcocdr’. le paramètre de connexion déclaré n’est absolument pas celui là.

Il faut utiliser la fonction getNextIdForColumn avec l’argument datasource, pas celle sans cet argument car elle tape sur le datasource par défaut.

	/**
	 * Get the next value of an ID column of a table using designated datasource
	 * @param datasource Data source name
	 * @param table Table name
	 * @param column Column name
	 * @return Next ID
	 */
	public String getNextIdForColumn(String datasource, String table, String column)

Cf. https://www.simplicite.io/resources/4.0/javadoc/com/simplicite/util/Grant.html#getNextIdForColumn-java.lang.String-java.lang.String-java.lang.String-

ok pour le getNextIdForColumn.

mais le hook initCreate n’est cependant pas exécuté.

Il n’y a pas de différence de traitement au niveau des hooks entre un object tapant sur le datasource par défaut et sur un objet tapant sur un datasource additionnel.

il y a pourtant une différence de comportement.

j’ai enlevé le datasource, le initcreate est exécuté.
je remet le datasource, le initcreate n’est pas exécuté.

Il doit sans doute y avoir une erreur avant l’appel de l’initCreate sur le datasource externe

il n’y a aucun message dans les logs

Je viens de faire un test avec une instance avec un base par défaut en HSQLDB et une base externe MySQL,

J’y ai configuré 2 objets, l’un point sur la table test de la base par défaut, l’autre sur la table test de la base externe.

Pour chacun de de ces objets j’ai implémenté un initCreate, je ne constate pas de différence sur les 2 objets, le initCreate est bien appelé dans les 2 cas (et j’ai bien pu créer des records dans les 2 cas).

Voici le test en vidéo:

Je te laisse regarder comment c’est configuré:

https://extdbtest.bretagne.simplicite.io (designer/designer)