2014-06-26 16 views
6

Piszę aplikację, która używa hibernacji + JPA jako ORM i postgresql 9.3 jako zaplecza bazy danych i muszę zareagować z pewnym kodem java do niektórych zdarzeń bazy danych.
Aby być bardziej precyzyjnym chcę zbudować wyzwalacz, który używa pg_notify(), gdy nowy wiersz jest wstawiony do tabeli.
Przeczytałem o tym, ale wszystkie tutoriale były z bezpośrednim połączeniem jdbc, a nie przez hibernację.
Ja (myślę, że ja) nie można używać zdarzeń hibernacji, ponieważ wiersze nie są wstawiane przez hibernację, ale przez aplikację innej firmy.Hibernate postgresql powiadamia funkcjonalność

Czy istnieje sposób, aby otrzymywać powiadomienia wysyłane z pg_notify przez hibernację?

- aktualizacja
Teraz mam ClassCastException:

java.lang.ClassCastException: com.sun.gjc.spi.jdbc40.ConnectionWrapper40 cannot be cast to org.postgresql.PGConnection 
    at com.xxx.core.impl.dao.PostgresqlLowLevelNotificationDAOImpl$1.execute(PostgresqlLowLevelNotificationDAOImpl.java:36) 
    at com.xxx.core.impl.dao.PostgresqlLowLevelNotificationDAOImpl$1.execute(PostgresqlLowLevelNotificationDAOImpl.java:1) 

muszę wspomnieć, że używam GlassFish 4.0 jako AS. Pula połączeń jest tworzona na glassfish i jest dostępna przez aplikację za pośrednictwem jndi. Również EntityManager jest wstrzykiwany przez pojemnik ze sprężyną. Tu jest mój kodu:

@Named 
public class PostgresqlLowLevelNotificationDAOImpl implements PostgresqlLowLevelNotificationDAO{ 

    @PersistenceContext(type =PersistenceContextType.TRANSACTION,synchronization=SynchronizationType.SYNCHRONIZED,unitName="CCPU") 
    private EntityManager em; 

@Override 
public ArrayList<PGNotification> getNotifications(){ 

    Session session = em.unwrap(Session.class); 

    PGNotification[] notifications = session.doReturningWork(new ReturningWork<PGNotification[]>() { 

     @Override 
     public PGNotification[] execute(Connection connection) throws SQLException { 
      PGNotification[] notifications = ((PGConnection) connection).getNotifications(); 
      return notifications; 
     } 

    }); 

    return (ArrayList) Arrays.asList(notifications); 
} 

}

- aktualizacja
mam naprawione classcast wyjątek:

@Override 
public ArrayList<PGNotification> getNotifications(){ 

    Session session = em.unwrap(Session.class); 


    PGNotification[] notifications = session.doReturningWork(new ReturningWork<PGNotification[]>() { 

     @Override 
     public PGNotification[] execute(Connection connection) throws SQLException { 

      PGConnection pgc = null; 

      if (connection.isWrapperFor(PGConnection.class)) { 
       pgc = (PGConnection) connection.unwrap(PGConnection.class); 
      }        

      PGNotification[] notifications = pgc.getNotifications();     
      return notifications; 
     } 
    }); 

Ale to wciąż wydaje się, że nie otrzymują powiadomień.

Aktualizacja ---
Po I wprowadziły rozwiązania zaproponowanego przez Neila mam ten błąd w GlassFish dzienników kiedy undeploy aplikacji:

2014-06-27T11:03:24.278+0300|SEVERE: The web application [/myApp] created a ThreadLocal with key of type [io.netty.buffer.PooledByteBufAllocator$1] (value [[email protected]]) and a value of type [io.netty.buffer.PoolThreadCache] (value [[email protected]]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak. 
2014-06-27T11:03:24.279+0300|SEVERE: The web application [/myApp] created a ThreadLocal with key of type [io.netty.util.Recycler$1] (value [[email protected]]) and a value of type [io.netty.util.Recycler.Stack] (value [[email protected]]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak. 
2014-06-27T11:03:24.279+0300|SEVERE: The web application [/myApp] created a ThreadLocal with key of type [io.netty.util.Recycler$1] (value [[email protected]]) and a value of type [io.netty.util.Recycler.Stack] (value [[email protected]]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak. 
2014-06-27T11:03:24.280+0300|SEVERE: The web application [/myApp] created a ThreadLocal with key of type [io.netty.util.internal.ThreadLocalRandom$2] (value [[email protected]]) and a value of type [io.netty.util.internal.ThreadLocalRandom] (value [[email protected]]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak. 
2014-06-27T11:03:24.280+0300|SEVERE: The web application [/myApp] created a ThreadLocal with key of type [io.netty.util.Recycler$1] (value [[email protected]]) and a value of type [io.netty.util.Recycler.Stack] (value [[email protected]]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak. 
2014-06-27T11:03:24.281+0300|SEVERE: The web application [/myApp] created a ThreadLocal with key of type [io.netty.util.Recycler$1] (value [[email protected]]) and a value of type [io.netty.util.Recycler.Stack] (value [[email protected]]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak. 
2014-06-27T11:03:24.282+0300|SEVERE: The web application [/myApp] created a ThreadLocal with key of type [io.netty.util.concurrent.DefaultPromise$1] (value [[email protected]]) and a value of type [java.lang.Integer] (value [0]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak. 
2014-06-27T11:03:24.282+0300|SEVERE: The web application [/myApp] created a ThreadLocal with key of type [io.netty.util.Recycler$1] (value [[email protected]]) and a value of type [io.netty.util.Recycler.Stack] (value [[email protected]]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak. 
2014-06-27T11:03:24.282+0300|SEVERE: The web application [/myApp] created a ThreadLocal with key of type [io.netty.buffer.PooledByteBufAllocator$1] (value [[email protected]]) and a value of type [io.netty.buffer.PoolThreadCache] (value [[email protected]]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak. 
2014-06-27T11:03:24.283+0300|SEVERE: The web application [/myApp] created a ThreadLocal with key of type [io.netty.util.Recycler$1] (value [[email protected]]) and a value of type [io.netty.util.Recycler.Stack] (value [[email protected]]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak. 
2014-06-27T11:03:24.283+0300|SEVERE: The web application [/myApp] created a ThreadLocal with key of type [io.netty.util.Recycler$1] (value [[email protected]]) and a value of type [io.netty.util.Recycler.Stack] (value [[email protected]]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak. 
2014-06-27T11:03:24.283+0300|SEVERE: The web application [/myApp] created a ThreadLocal with key of type [io.netty.buffer.PooledByteBufAllocator$1] (value [[email protected]]) and a value of type [io.netty.buffer.PoolThreadCache] (value [[email protected]]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak. 

muszę wspomnieć, że zniszczyć() metoda jest wywoływana, gdy aplikacja została wycofana. A jeśli szpieguję z visualVM wątek wciąż żyje po tym, jak aplikacja została usunięta.

public void destroy(){ 

    try{ 
     Statement statement = pgConnection.createStatement();     
     statement.addBatch("UNLISTEN xxxTest"); 
     statement.executeBatch(); 
     statement.close();   
    }catch(SQLException sqle) { 
     sqle.printStackTrace(); 
    } 

} 

Odpowiedz

3
  1. Dlaczego musisz hibernacji tutaj? Po prostu użyj JDBC. Prawdopodobnie chcesz wywołać zdarzenie w całej aplikacji (być może wysłać wiadomość e-mail lub biuletyn ehcache), a jeśli musisz coś zrobić w trybie hibernacji, zasubskrybuj to wydarzenie i zrób coś za pomocą Hibernuj.

  2. http://impossibl.github.io/pgjdbc-ng/ to Twój przyjaciel. Nie wymaga się sondowania.

Zobacz http://blog.databasepatterns.com/2014/04/postgresql-nofify-websocket-spring-mvc.html

+0

Potrzebuję hibernacji, ponieważ chciałem być typową konfiguracją aplikacji i korzystać z tych samych zasobów. Dzięki za wskazówki, przyjrzę się. –

+1

Mam zaimplementowane z pgjdbc-ng i bez hibernacji i wydaje się, że działa :) dzięki Neil. –

+0

Wygląda na to, że są 2 problemy: 1. Istnieje jeden wątek, który pozostaje aktywny, nawet jeśli aplikacja nie zostanie wdrożona. 2. Działa tylko wtedy, gdy dwa razy wdrożę aplikację. Myślę, że ma to coś wspólnego z pozostałym otwartym wątkiem ... –

2

Hibernate nie ma bezpośredniego wsparcia dla powiadomień PostgreSL, ponieważ jest to cecha specyficzna baza danych, która nie jest obsługiwana przez wszystkich dostawców DB i nie pasuje do odpowiedzialności ramowej ORM.

Mimo to możesz spróbować podłączyć go do bieżącej transakcji. Potrzebujesz dostępu do bieżącego połączenia z bazą danych do add the listening hook.

Można to zrobić przy wsparciu Session.doWork():

session.doWork(new Work() { 
    @Override 
    public void execute(Connection connection) throws SQLException { 
     //add some statement if it's required 
     PGNotification notifications[] = ((PGConnection) connection).getNotifications();   
    } 
}); 
+0

Dzięki Vlad, 'll sprawdzić, i wrócić z przyjętą odpowiedzi :) –

+0

Proszę zobaczyć notatkę w http://jdbc.postgresql.org/documentation/92/listennotify .html jednak - potrzebujesz podróży w obie strony, jak pusta instrukcja. Dodaję teraz funkcję, która zamiast tego wyświetli komunikat protokołu synchronizacji. –

+0

Zaktualizowałem przykład, dziękuję za odpowiedź. Wygląda na to, że jest to możliwe, chociaż nigdy wcześniej tego nie próbowałem. –

Powiązane problemy