JPA Hibernate Call-Postgres-Funktion Void Zurückgeben MappingException:
Ich habe ein problem wo ich bin immer ein: org.hibernate.MappingException: Keine Dialekt-mapping für JDBC-Typ: 1111 wenn Sie versuchen zu nennen, eine postgres-Funktion mit JPA erstellen Sie native query.
Erstellte ich eine EJB-timer in einem startup singleton ausgeführt, eine Postgres-Funktion alle 6 Stunden. Die Funktion gibt void zurück und sucht nach abgelaufener Datensätze löscht Sie, und einige Status-updates. Es nimmt keine Argumente und gibt void zurück.
- Postgres-Funktion läuft perfekt, wenn ich rufe es mit PgAdmin-Abfrage-tool (wählen Sie die Funktion();) und gibt void zurück.
- Wenn ich das bereitstellen der app auf Glassfish 3.1.1 bekomme ich eine Ausnahme und ein Fehler bereitstellen.
Dies ist die (verkürzte) stack trace:
WARNING: A system exception occurred during an invocation on EJB UserQueryBean method public void com.mysoftwareco.entity.utility.UserQueryBean.runRequestCleanup()
javax.ejb.TransactionRolledbackLocalException: Exception thrown from bean
...STACK TRACE BLAH BLAH BLAH ...
Caused by: javax.persistence.PersistenceException: org.hibernate.MappingException: No Dialect mapping for JDBC type: 1111
Hier ist der code:
Erste, der PPV stuff:
public void runRequestCleanup() {
String queryString = "SELECT a_function_that_hibernate_chokes_on()";
Query query = em.createNativeQuery(queryString);
Object result = query.getSingleResult();
}
Dies ist die singleton-Aufruf:
@Startup
@Singleton
public class RequestCleanupTimer {
@Resource
TimerService timerService;
@EJB
UserQueryBean queryBean;
@PostConstruct
@Schedule(hour = "*/6")
void runCleanupTimer() {
queryBean.runRequestCleanup();
}
}
Und die Funktion:
CREATE OR REPLACE FUNCTION a_function_that_hibernate_chokes_on()
RETURNS void AS
$BODY$
DECLARE
var_field_id myTable.field_id%TYPE;
BEGIN
FOR var_field_id IN
select field_id from myTable
where status = 'some status'
and disposition = 'some disposition'
and valid_through < now()
LOOP
BEGIN
-- Do Stuff
END;
END LOOP;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
InformationsquelleAutor Bill Rosmus | 2012-09-24
Du musst angemeldet sein, um einen Kommentar abzugeben.
Könnte dies ein hack, aber bei mir hat es geklappt und ist ziemlich einfach. Ändern Sie einfach die Abfrage:
Nun gibt es einen korrekten integer-und Ruhezustand ist glücklich.
Beide verkaufen und @Kikin-Sama 's Methode gearbeitet.
InformationsquelleAutor bezmax
Hatte ich genug rumgespielt mit JPA versucht, es zu erhalten, um eine gespeicherte Prozedur auszuführen.
Landete ich unter Verwendung von JDBC mit einer vorbereiteten Anweisung. Ich habe es in 15 Minuten, nach mehreren erfolglosen Stunden versucht zu passen, einen quadratischen Pflock in ein rundes Loch. Ich rief das gleiche jndi-datasource-meine Hartnäckigkeit-Einheit verwendet, um eine Verbindung zu erhalten, erstellt eine vorbereitete Anweisung und geschlossen, wenn Sie fertig sind.
Also, wenn Sie brauchen, um eine gespeicherte Prozedur auszuführen (oder Postgres-Funktion) aus einer (jetzt meist) JPA app, hier ist was für mich gearbeitet:
Scheint es ein schreckliches versehen die einfache Möglichkeit zum ausführen einer Funktion oder einer gespeicherten Prozedur auf dem server, von JPA; vor allem eine, die nichts zurückgibt, außer leere, oder die Anzahl der betroffenen Zeilen. Und wenn es beabsichtigt war ... kein Kommentar.
Edit: Hinzugefügt enger Verbindung.
InformationsquelleAutor Bill Rosmus
Es scheint, dass das problem tritt auf, wenn die postgres stored procedure gibt void zurück. Versuchen Sie, ändern Sie den Rückgabetyp wieder einige dummy-Wert, vielleicht ein string. Dies funktionierte in meinem Fall.
InformationsquelleAutor jdklett
Diesem wurde geschrieben vor einiger Zeit, aber ich hatte das ähnliche Problem. Wie gesagt, Hibernate sieht allergisch ungültig und werden versuchen, sperren Sie in mit der return-jeder Zeit geben. Aus meiner Sicht ist dies eine gute Praxis, wie Sie sollte normalerweise immer eine Rückkehr zumindest angeben, wenn es gelungen ist: wirft Ausnahme ist oft beleidigend.
Doch, Hibernate bietet eine Möglichkeit, diese zu umgehen Einschränkungen: org.hibernate.jdbc.Arbeit
Können Sie ganz einfach reproduzieren, was erforderlich war, in einer kleinen Klasse:
Nun kann man es nennen, wenn Sie wollen, indem Sie
VoidProcedureWork.execute(hibernateSession, sqlQuery);
Werden Sie feststellen, zwei Dinge über diese Klasse:
1) ich NICHT die Verbindung schließen. Ich lasse es so, weil ich nicht weiß, wer öffnete die Verbindung, wie und warum. Ist die gleiche Verbindung in einer Transaktion verwendet werden? Wenn ich es schließen, ant jemand nach verwendet, wird es krachen? Etc. Ich nicht code, Hibernate und nicht mit der Verbindung.open(). Daher, ich nicht schließen und davon ausgehen, was es geöffnet wird, schließen Sie es auch.
2) Es ist mehr der prozeduralen Programmierung als OOP. Ich weiß, aber ich bin faul: es ist einfacher (und übersichtlicher imo) zu verwenden VoidProcedureWork.execute(session, sql) als neue VoidProcedureWork(sql).execute(session). Oder noch schlimmer: reproduzieren Sie den code ausführen, jedes mal, wenn ich verwenden möchten, die kleinen trick (session.doWork(neue VoidProcedureWork(sql)) mit Ausnahme der Verarbeitung).
InformationsquelleAutor Martin Brassard
Für zukünftige Besucher von diesem Problem, eine Besetzung gearbeitet haben würde, auch. geschrieben am dieser thread sowie
InformationsquelleAutor srex
Dude! Es ist so einfach wie das zitieren der name der Funktion. Etwa so:
InformationsquelleAutor Kikin-Sama