Fichier de modèle de requête

Le fichier de modèle de requête constitue un mécanisme vous permettant de mapper facilement une requête de votre modèle logique avec une ou plusieurs instructions SQL. Les ressources SQL sont conservées dans des fichiers distincts, qui sont isolés du code Java de la phase d'exécution. Ce modèle aide les administrateurs de la base de données et les programmeurs à localiser et à analyser les instructions SQL. De plus, les modifications du code SQL utilisées pour les requêtes ne requièrent pas une recompilation du code Java. En outre, l'addition de nouvelle colonnes dans des tables existantes ne requiert pas nécessairement de modifications des instructions SQL qui les utilisent. Les informations de colonnes sont scindées dans la section SYMBOL_DEFINITIONS.

Emplacement et attribution de nom au fichier de modèle de requête

Un module de service peut comporter un ou plusieurs fichiers de modèle de requête. Ajoutez aux fichiers de modèle de requête le préfixe "wc-query" et utilisez l'extension .tpl.

Les fichiers de modèle de requête par défaut sont situés dans le répertoire suivant workspace_dir\WC\xml\config\com.ibm.commerce.servicemodule

Vous pouvez ajouter de nouvelles requêtes, ou étendre celles fournies avec le produit, en plaçant vos fichiers de modèle de requête sous le répertoire de configuration d'extension de votre module de service.

Les fichiers de modèle de requête personnalisés doivent être placés dans le répertoire suivant : workspace_dir\WC\wc\xml\config\com.ibm.commerce.servicemodule-extPar exemple, un fichier de modèle de requête de catalogue se trouve dans le répertoire suivant : xml\config\com.ibm.commerce.catalog-ext.

Remarque : L'ajout de nouvelles colonnes à vos tables personnalisées nécessite de modifier, à l'aide de l'assistant couche service de données, les objets SDO physiques qui les représentent.

Syntaxe et chargement du fichier de modèle de requête

Les fichiers de modèle de requête sont chargés par ordre alphanumérique ascendant. Lorsque les fichiers contenant des définitions de requêtes sont chargés, les nouvelles requêtes écrasent les requêtes précédemment chargées.

Les blocs dans le modèle de requête doivent suivre l'ordre suivant :

  1. BEGIN_SYMBOL_DEFINITIONS
  2. END_SYMBOL_DEFINITIONS
  3. BEGIN_XPATH_TO_SQL_STATEMENT
  4. END_XPATH_TO_SQL_STATEMENT
  5. BEGIN_ ASSOCIATION_SQL_STATEMENT
  6. END_ ASSOCIATION_SQL_STATEMENT
  7. BEGIN_SQL_STATEMENT
  8. END_SQL_STATEMENT
  9. BEGIN_PROFILE
  10. END_PROFILE.
Les blocs BEGIN_PROFILE_ALIASES et END_PROFILE_ALIASES peuvent être définis n'importe où dans un fichier de modèle de requête.
Remarque :
  • Chaque ligne ou bloc mis en commentaire doit débuter par <!-- et se terminer par -->. Une ligne ou un bloc en commentaire peuvent être placés à n'importe quel endroit dans le fichier.
  • Au cours du développement, vous voudrez peut-être modifier et recharger un fichier de modèle de requête sans avoir besoin de redémarrer le serveur. Vous pouvez utiliser un fichier .reloadconfig. Pour plus d'informations sur l'utilisation d'un fichier .reloadconfig, consultez la rubrique sur le rechargement de la configuration d'un module de service BOD.

Organisation du fichier de modèle de requête

Un fichier de modèle de requête est composé de cinq sections, les deux premières étant obligatoires :
SYMBOL_DEFINITIONS
Cette section de définition contient des symboles de colonnes utilisés et référencés dans la liste SELECT des instructions SQL de votre modèle. Si votre schéma physique venait à changer, vous pouvez modifier les symboles sans avoir à recomposer vos instructions SQL. La définition de symboles est similaire à la définition de constantes dans les langages de programmation. Vous pouvez définir des informations à un emplacement et les réutiliser à plusieurs endroits. Cette approche aide à situer les éléments à mettre à jour si des modifications ultérieures sont requises. Lorsque vous définissez un sous-ensemble des colonnes à sélectionner dans une table, vérifiez que la requête inclue les colonnes de clé primaire et de clés externes.
  • Un seul bloc BEGIN_SYMBOL_DEFINITIONS, END_SYMBOL_DEFINITIONS doit exister par fichier de modèle de requête.
  • Tous les symboles doivent être définis dans le bloc BEGIN_SYMBOL_DEFINITIONS.
  • Il peut inclure des lignes de commentaires ou des lignes de définition de symbole. La définition d'un symbole doit couvrir une seule ligne.
  • Une ligne de définition de symbole contient la définition d'un seul symbole.
  • Le nom du symbole, compris entre "COLS:" et '=', est son identificateur unique. Les caractères admis dans les noms de symbole sont : a-z, A-Z et 0-9.
  • Si le caractère générique (*) est utilisé dans la définition de colonne, les noms de colonnes sont extraits des Métadonnées objet-relationnel et les définitions de colonne ont une portée de fichier.
Exemple
BEGIN_SYMBOL_DEFINITIONS

	COLS:CATENTRY_ID=CATENTRY:CATENTRY_ID
	COLS:CATENTRY=CATENTRY:*	
	COLS:CATENTDESC=CATENTDESC:CATENTRY_ID,SHORTDESCRIPTION, OPTCOUNTER

END_SYMBOL_DEFINITIONS
Remarque : Lorsque vous définissez un sous-ensemble de colonnes à sélectionner dans une table, incluez la colonne OPTCOUNTER. Voir Verrouillage optimiste pour plus d'informations. Ajoutez toujours une colonne OPTCOUNTER à vos tables personnalisées. Par exemple :
COLS:DMACTIVITY_NAME=DMACTIVITY:DMACTIVITY_ID, NAME, OPTCOUNTER 
XPATH_TO_SQL_STATEMENT
L'instruction XPATH_TO_SQL_STATEMENT lie les couches logiques et physiques en mappant directement une clé XPath à une instruction SQL. Le nom de l'instruction XPATH_TO_SQL_STATEMENT est la clé de l'expression XPath. Pour les requêtes à une seule étape, ce nom est la combinaison de la clé XPath et du profil d'accès. Par exemple, si la clé XPath est /CatalogEntry[CatalogEntryIdentifier[ExternalIdentifier[(PartNumber=)]]] et que le profil d'accès est IBM_Admin_Details, le nom d'un modèle en une seule étape est /CatalogEntry[CatalogEntryIdentifier[ExternalIdentifier[(PartNumber=)]]]+IBM_Admin_Details. Vous pouvez utiliser l'utilitaire cs_xpathkey pour obtenir la clé XPath d'une expression XPath.
Remarque : Le mappage de clé XPath à requête SQL peut être remplacé. Si une clé XPath est définie dans plusieurs fichiers de modèle de requête, celle définie dans le dernier fichier chargé supplante les autres.
  • Il peut y avoir plusieurs blocs BEGIN_XPATH_TO_SQL_STATEMENT, END_XPATH_TO_SQL_STATEMENT.
  • Chaque bloc définit une seule instruction SQL.
  • Dans chaque bloc doivent être définis les éléments 'name' et 'base_table'.
  • Les espaces ne sont pas admis dans le nom.
  • L'instruction SQL peut couvrir plusieurs lignes et doit être définie en dernier dans le bloc.
  • La balise facultative dbtype est spécifiée lorsqu'une instruction SQL est spécifique à la plateforme de base de données. Cette balise est utile en cas de développement d'instructions SQL pour plusieurs plateformes de base de données. Ces instructions peuvent être incluses dans un même fichier de modèle. Les valeurs valides pour la balise dbtype sont : "db2", "oracle", "derby" et "any". Les requêtes dans lesquelles cette balise n'est pas spécifiée s'appliquent à toutes les plateformes de base de données. Si vous incluez une requête pour une plateforme de base de données spécifique, incluez-en également une par défaut (avec valeur dbtype "any") destinée aux autres plateformes.
  • Les éléments de ce bloc doivent respecter l'ordre comme indiqué dans l'exemple.
    Exemple
    BEGIN_XPATH_TO_SQL_STATEMENT
    name=/CatalogEntry[CatalogEntryIdentifier[ExternalIdentifier[(PartNumber=)]]]
    base_table=CATENTRY
    sql=
    SELECT 
    	CATENTRY.$COLS:CATENTRY_ID$
    FROM
    	CATENTRY
    JOIN
    	STORECENT ON (CATENTRY.CATENTRY_ID = STORECENT.CATENTRY_ID AND
    	STORECENT.STOREENT_ID = $CTX:STORE_ID$)
    WHERE
    	CATENTRY.PARTNUMBER IN (?PartNumber?) 
    	AND CATENTRY.MARKFORDELETE = 0
    
    END_XPATH_TO_SQL_STATEMENT 
    
  • Le fragment précédent contient des balises CTX qui représentent des contextes métier. La couche Service de données permet au développeur de spécifier une balise spéciale, $CTX:KEY$, dans le modèle SQL. La couche Service de données utilise cette balise pour aider à l'extraction des informations contextuelles de la base de données. Cette balise est remplacée en phase d'exécution par la valeur de la propriété du contexte (par exemple, l'ID de langue ou de magasin) correspondant à 'KEY'.

    Pour plus d'informations sur ces balises, reportez-vous à la rubrique sur les balises de fichier de modèle de requête.

  • L'instruction SQL peut être écrite pour la gestion de contenu d'espace de travail.

    Pour plus d'informations sur l'écriture pour la gestion de contenu d'espace de travail, consultez la rubrique sur les techniques d'amélioration des performances des requêtes SQL dans des espaces de travail de la couche Service de données.

ASSOCIATION_SQL_STATEMENT
Les instructions SQL associées définissent une requête SQL spécifique. Ces requêtes peuvent ensuite être réutilisées pour construire des profils d'accès différents définis dans la section PROFILE.
  • Il peut y avoir plusieurs blocs BEGIN_ ASSOCIATION_SQL_STATEMENT, END_ ASSOCIATION_SQL_STATEMENT.
  • Chaque bloc peut définir tout au plus une instruction SQL.
  • Les règles du bloc XPATH_TO_SQL_STATEMENT s'appliquent dans celui-ci.
  • Le nom est l'identificateur unique de ASSOCIATION_SQL_STATEMENT.
Exemple
BEGIN_ASSOCIATION_SQL_STATEMENT
	name=IBM_CatalogEntryWithDescription
	base_table=CATENTRY
	sql=
	     SELECT 
	        CATENTRY.$COLS:CATENTRY$,
                CATENTDESC.$COLS:CATENTDESC$
	     FROM
	        CATENTRY
	           LEFT OUTER JOIN CATENTDESC ON 
                     (CATENTDESC.CATENTRY_ID = CATENTRY.CATENTRY_ID  AND 
                      CATENTDESC.LANGUAGE_ID IN ($CONTROL:LANGUAGES$))
	     WHERE
                CATENTRY.CATENTRY_ID IN ($ENTITY_PKS$)
END_ASSOCIATION_SQL_STATEMENT
SQL_STATEMENT
Cette section contient des instructions SQL nommées. Les instructions SQL sont exécutées directement via l'interface JDBC à l'aide de la classe JDBCQueryService. Cette classe est similaire à la classe auxiliaire JDBC de bean session utilisée par les modules de service. Cette section peut contenir des instructions select qui utilisent des fonctions d'agrégation, telles que sum() ou avg(). En conséquence de l'utilisation de ces fonctions, les requêtes ne sont pas mappées sur des objets Java physiques par des métadonnées relationnelles d'objet.

Dans certaines circonstances, vous pouvez avoir besoin d'exécuter des instructions SQL pour mettre à jour, supprimer ou extraire des données indépendantes du modèle de données. Une opération commerciale peut, par exemple, insérer ou supprimer des enregistrements dans des tables de données non définies dans le modèle logique. L'opération commerciale peut également mettre à jour des objets de données multiples qui sont plus efficaces pour émettre une instruction SQL directe plutôt que d'utiliser la couche Service de données pour extraire et mettre à jour chaque objet.

Exemple
BEGIN_SQL_STATEMENT
	name=IBM_Update_DeleteCatalogEntry
	base_table=CATENTRY
	sql= UPDATE CATENTRY   	
				SET CATENTRY.PARTNUMBER=
	     				CASE WHEN 
	     					LENGTH(CATENTRY.PARTNUMBER||'-'||$DB:CURRENT_TIMESTAMP$)<=64 
	     				THEN 
	     					CATENTRY.PARTNUMBER||'-'||$DB:CURRENT_TIMESTAMP$  
	     				ELSE 
	     					SUBSTR(CATENTRY.PARTNUMBER,1,64-LENGTH(''||$DB:CURRENT_TIMESTAMP$)-1)||'-'||$DB:CURRENT_TIMESTAMP$ END
	     				,CATENTRY.MARKFORDELETE=1
	     	WHERE
			CATENTRY.CATENTRY_ID=?catalogEntryId? 
			OR CATENTRY.CATENTRY_ID IN (SELECT CATENTREL.CATENTRY_ID_CHILD FROM CATENTREL WHERE CATENTREL.CATENTRY_ID_PARENT=?catalogEntryId?)
END_SQL_STATEMENT	

La classe JDBCQueryService prend en charge les instructions de mise à jour, d'insertion et de suppression par lots via l'interface de mise à jour par lots executeBatchUpdate.

Remarque : La section SQL_STATEMENT figure uniquement dans le fichier wc-query-utilities.tpl. Il s'agit d'une convention spéciale pour un fichier de modèle de requête contenant ces instructions SQL nommées.
Remarque : Vous ne devez jamais lire ou mettre à jour les mêmes données à l'aide de JDBCQueryService et de PhysicalDataContainer dans la même transaction. Si vous le faites, il est possible que vous lisiez des données périmées ou que des données corrompues parviennent à la base de données.
L'instruction SQL peut être écrite pour la gestion de contenu d'espace de travail. Pour plus d'informations sur l'écriture pour la gestion de contenu d'espace de travail, consultez la rubrique sur les techniques d'amélioration des performances des requêtes SQL dans des espaces de travail de la couche Service de données.
PROFILE
Cette section définit des profils d'accès utilisant des instructions SQL associées. Le cas échéant, plusieurs instructions SQL associées peuvent être utilisées par un profil. Les différentes instructions SQL associées sont exécutées à tour de rôle et leurs résultats sont fusionnés à l'aide d'une classe GraphComposer.

Les requêtes associées à un profil d'accès doivent toujours être définies dans le même fichier où ce profil est défini , hormis s'il s'agit d'une extension de profil d'accès. Le mécanisme d'extension vous permet de réutiliser les instructions SQL associées par défaut sans besoin de les redéfinir dans votre fichier de modèle de requête personnalisé.

  • Il peut y avoir plusieurs blocs BEGIN_PROFILE, END_PROFILE.
  • Tous les blocs de profils doivent être situés à la fin du fichier.
  • Chaque bloc définit un nom de profil et ce nom est l'identificateur unique du profil.
  • Chaque bloc de profil ne peut avoir qu'un seul bloc BEGIN_ENTITY, END-ENTITY et dans chaque bloc 'entity' :
    • base_table doit être défini.
    • Une ou plusieurs instructions 'associated_sql_statement' associées peuvent être définies. L'instruction associated_sql_statement associée doit correspondre à l'un des noms ASSOCIATION_SQL_STATEMENT définis. De plus, le nom base_table défini dans le bloc d'entité doit correspondre au nom base_table dans les requêtes homologues du bloc ASSOCIATION_SQL_STATEMENT et du bloc XPATH_TO_SQL_STATEMENT utilisé dans le profil d'accès.
    • Un Composeur de graphique facultatif peut être spécifié dans le bloc 'entity'. Si className est spécifié, il doit inclure le chemin d'accès complet de la classe, laquelle doit constituer une sous-classe de subclass com.ibm.is.component.dsl.GraphComposer.
Exemple
BEGIN_PROFILE 
 name=IBM_Admin_Summary
 BEGIN_ENTITY
   base_table=CATENTRY
   associated_sql_statement=IBM_CatalogEntryWithDescription
 END_ENTITY
END_PROFILE
PROFILE_ALIASES
Utilisez la section PROFILE_ALIASES pour définir les alias des profils. Les alias ont une étendue globale et sont utilisés pour prendre en charge les profils d'accès obsolètes qui sont renommés. Vous pouvez spécifier des alias pour différents profils d'accès dans un seul bloc BEGIN_PROFILE_ALIASES - END_PROFILE_ALIASES lorsque les profils s'appliquent à la même table de base, par exemple, le même nom.
Par exemple, le code suivant définit l'IBM_CatalogAttachmentReference et l'IBM_CatAttachment comme alias du profil IBM_Admin_CatalogAttachmentReference.
BEGIN_PROFILE_ALIASES
  base_table=CATALOG
  IBM_CatalogAttachmentReference=IBM_Admin_CatalogAttachmentReference
  IBM_CatAttachment=IBM_Admin_CatalogAttachmentReference
END_PROFILE_ALIASES

Prise en charge des alias de colonne

Pour éviter l'ambiguïté dans la sélection de colonnes ayant des noms identiques dans des tables différentes, des alias de colonne sont utilisés. Le préfixe d'alias de colonne peut être spécifié avant une référence de symbole de colonne. La syntaxe générale de la référence de symbole de colonne est :

[<table_alias>.][<columns_alias_prefix>]$COLS:<column_symbol_name>$
Par exemple :

WITH TEMP_TABLE AS (
SELECT 
      CATENTRY.CE_$COLS:CATENTRY_ID$, ATTRVALUE.ATTR_$COLS:ATTRVALUE$, ATTRVALUE2.ATTR2_$COLS:ATTRVALUE$
FROM CATENTRY, ATTRVALUE 
JOIN ATTRIBUTE 
      ON ATTRIBUTE.LANGUAGE_ID = ATTRVALUE.LANGUAGE_ID 
      AND ATTRIBUTE.ATTRIBUTE_ID = ATTRVALUE.ATTRIBUTE_ID 
LEFT OUTER JOIN ATTRVALUE ATTRVALUE2 
      ON ATTRIBUTE.ATTRIBUTE_ID = ATTRVALUE2.ATTRIBUTE_ID 
      AND ATTRVALUE2.CATENTRY_ID = 0 
      AND ATTRIBUTE.LANGUAGE_ID = ATTRVALUE2.LANGUAGE_ID 
WHERE CATENTRY.CATENTRY_ID IN ($ENTITY_PKS$) 
      AND ATTRVALUE.CATENTRY_ID = CATENTRY.CATENTRY_ID 
) SELECT * FROM TEMP_TABLE
Supposons que les définitions de symbole suivantes existent :

COLS:CATENTRY_ID=CATENTRY:CATENTRY_ID
COLS:ATTRVALUE=ATTRVALUE:ATTRVALUE_ID,LANGUAGE_ID
La requête obtenue se présente comme suit :

WITH TEMP_TABLE AS (
SELECT 
      CATENTRY.CATENTRY_ID CE_CATENTRY_ID, 
      ATTRVALUE.ATTRVALUE_ID ATTR_ATTRVALUE_ID, ATTRVALUE.LANGUAGE_ID ATTR_LANGUAGE_ID,                         
 ATTRVALUE2.ATTRVALUE_ID ATTR2_ATTRVALUE_ID, ATTRVALUE2.LANGUAGE_ID ATTR2_ATTRVALUE_ID
FROM CATENTRY, ATTRVALUE 
JOIN ATTRIBUTE 
      ON ATTRIBUTE.LANGUAGE_ID = ATTRVALUE.LANGUAGE_ID 
      AND ATTRIBUTE.ATTRIBUTE_ID = ATTRVALUE.ATTRIBUTE_ID 
LEFT OUTER JOIN ATTRVALUE ATTRVALUE2 
      ON ATTRIBUTE.ATTRIBUTE_ID = ATTRVALUE2.ATTRIBUTE_ID 
      AND ATTRVALUE2.CATENTRY_ID = 0 
      AND ATTRIBUTE.LANGUAGE_ID = ATTRVALUE2.LANGUAGE_ID 
WHERE CATENTRY.CATENTRY_ID IN ($ENTITY_PKS$) 
      AND ATTRVALUE.CATENTRY_ID = CATENTRY.CATENTRY_ID 
) SELECT * FROM TEMP_TABLE