2010-06-02 8 views
3

Je suis obligé de gérer un champ d'auto-incrément à partir du code. J'ai décidé d'écrire une procédure stockée pour le faire pour moi. L'idée est d'avoir une procédure qui insère une nouvelle ligne et renvoie la valeur auto-incrémentée à Java afin que je puisse travailler plus loin. Ce qui suit est ce que j'ai jusqu'à présent. Je ne sais pas quoi changer pour combler les lacunes afin que tout fonctionne.Hibernate Stored Procédure Résultats

SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
CREATE PROCEDURE addNewMSO 
    @sourceApplication char(8), 
    @selectionStatusDate datetime = NULL, 
    @sysLstUpdtUserId char(10) 
AS 
BEGIN 
    SET NOCOUNT ON; 

    Declare @newVal int 
    SET @newVal = (select max(seqNo) from MemberSelectedOptions) + 1 

    INSERT INTO MemberSelectedOptions 
     ([SourceApplication] 
     ,[SeqNo] 
     ,[SelectionStatusDate] 
     ,[SysLstUpdtUserId]) 
VALUES 
     (@sourceApplication 
     ,@newVal 
     ,@selectionStatusDate 
     ,@sysLstUpdtUserId) 

END 
GO 

Ensuite, dans mon code Java j'ai ce qui suit.

@NamedNativeQuery(name="addNewMSO", 
    query="exec addNewMSO :sourceApplication :selectionStatusDate :sysLstUpdtUserId", callable=true) 

Et mon OAC appelle comme ça ...

Query q = session.getNamedQuery("addNewMSO"); 
q.setParameter("sourceApplication", mso.getSourceApplication()); 
q.setParameter("selectionStatusDate", mso.getSelectionStatusDate()); 
q.setParameter("sysLstUpdtUserId", mso.getSysLstUpdtUserId()); 
q.executeUpdate(); 

Même alors, cela ne fonctionne pas, parce que je reçois une erreur « requêtes scalaires natives pures ne sont pas encore pris en charge ». Donc je ne sais pas où aller ensuite. J'ai lu les documents Hibernate, mais je ne sais pas comment obtenir une valeur de retour du SP. Mais je ne peux même pas l'appeler ... pouah!

TIA pour toute aide.

Répondre

4

Si votre SP ne retourne pas un ensemble de résultats, alors je crains que vous deviez utiliser session.getConnection() et JDBC brut. Selon la documentation de mise en veille prolongée:

16.2.2. Using stored procedures for querying

Hibernate3 prend en charge les requêtes via des procédures stockées et fonctions. La majeure partie de la documentation suivante est équivalente pour les deux. La procédure/fonction stockée doit renvoyer un jeu de résultats en tant que premier paramètre de sortie pour pouvoir fonctionner avec Hibernate. (...)

16.2.2.1. Rules/limitations for using stored procedures

Vous ne pouvez pas utiliser des procédures stockées avec Mise en veille prolongée, sauf si vous suivez quelques règles de procédure/fonction . S'ils font ne suivent pas ces règles ils ne sont pas utilisable avec Hibernate. Si vous souhaitez toujours utiliser ces procédures, vous avez pour les exécuter via session.connection(). Les règles sont différentes pour chaque base de données, puisque les fournisseurs de bases de données ont des sémantiques/syntaxes de procédure différentes. Les requêtes de procédure stockée ne peuvent pas être avec setFirstResult()/setMaxResults(). La forme d'appel recommandée est la norme SQL92: { ? = call functionName(<parameters>) } ou { ? = call procedureName(<parameters>}. La syntaxe d'appel native n'est pas prise en charge.

(...)

Pour le serveur SQL Sybase ou MS les règles suivantes:

  • La procédure doit retourner un jeu de résultats. Notez que puisque ces serveurs peuvent retourner plusieurs ensembles de résultats et mettre à jour points, Hibernate va itérer les résultats et prendre le premier résultat que est un ensemble de résultats comme valeur de retour. Tout le reste sera jeté.
  • Si vous pouvez activer SET NOCOUNT ON dans votre procédure, il sera probablement plus efficace, mais ce n'est pas une exigence .
0

Disclaimer: Je ne suis pas familier avec WAY HIBERNATE, ni Java, mais de ce que je vous ai lu ci-dessus semblent avoir besoin d'avoir au moins un ResultSet pour que cela fonctionne! Étant donné la balise SQL-2005, je suppose que votre code est en T-SQL, par conséquent je tiens à souligner que votre code est 'imparfait' à cet égard qu'il MIGHT (oui, très petite chance, mais quand même) Il arrive qu'une autre connexion insère un nouvel enregistrement dans la table entre le moment où vous sélectionnez @newval et le moment où vous faites l'insertion réelle. Cela peut être résolu en utilisant le verrouillage, ou à mon humble avis plus simplement en mettant INSERT et SELECT dans une seule déclaration. Ajouter un ISNULL() fera également en sorte que si vous avez besoin de redémarrer avec une table vide, la procédure stockée fonctionnera comme prévu, même si elle n'a aucune valeur de départ à ajouter.

CREATE PROCEDURE addNewMSO 
@sourceApplication char(8), 
@selectionStatusDate datetime = NULL, 
@sysLstUpdtUserId char(10) 
AS 
BEGIN 
SET NOCOUNT ON; 

INSERT INTO MemberSelectedOptions 
    ([SourceApplication] 
    ,[SeqNo] 
    ,[SelectionStatusDate] 
    ,[SysLstUpdtUserId]) 
OUTPUT (inserted.[SeqNo]) 
SELECT [SourceApplication] = @sourceApplication, 
    [SeqNo]    = ISNULL((SELECT max([SeqNo]) FROM MemberSelectedOptions), 0) + 1, 
    [SelectionStatusDate] = @selectionStatusDate, 
    [SysLstUpdtUserId] = @sysLstUpdtUserId 
END 

La clause SORTIE retourne la nouvelle valeur insérée dans un jeu d'enregistrements qui, si je comprends les limites hibernate correctement, vous aider à la fois sur ce qui est pris en charge et ce qui est nécessaire.

Questions connexes