我正在编写一个使用hibernate + JPA作为ORM和postgresql 9.3作为数据库后端的应用程序,我需要对某些数据库事件做出反应.
更确切地说,我想在将新行插入表中时构建一个使用pg_notify()的触发器.
我已经读过这个,但所有的教程都是直接的jdbc连接,而不是通过hibernate.
我(认为我)不能使用hibernate事件,因为行不是通过hibernate插入的,而是通过第三方应用程序插入的.
有什么方法可以通过hibernate接收通过pg_notify发送的通知吗?
- 更新
现在我有一个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)
我必须提到我使用Glassfish 4.0作为AS.连接池在glassfish上创建,并通过jndi由app访问.此外,EntityManager由容器注入Spring.这是我的代码:
@Named public class PostgresqlLowLevelNotificationDAOImpl implements PostgresqlLowLevelNotificationDAO{ @PersistenceContext(type =PersistenceContextType.TRANSACTION,synchronization=SynchronizationType.SYNCHRONIZED,unitName="CCPU") private EntityManager em; @Override public ArrayListgetNotifications(){ Session session = em.unwrap(Session.class); PGNotification[] notifications = session.doReturningWork(new ReturningWork () { @Override public PGNotification[] execute(Connection connection) throws SQLException { PGNotification[] notifications = ((PGConnection) connection).getNotifications(); return notifications; } }); return (ArrayList) Arrays.asList(notifications); }
}
- 更新
我修复了classcast异常:
@Override public ArrayListgetNotifications(){ Session session = em.unwrap(Session.class); PGNotification[] notifications = session.doReturningWork(new ReturningWork () { @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; } });
但似乎我仍然没有收到通知.
更新---
在我实施了Neil提出的解决方案后,当我取消部署app时,我在glassfish日志中出现此错误:
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 [io.netty.buffer.PooledByteBufAllocator$1@28ad6479]) and a value of type [io.netty.buffer.PoolThreadCache] (value [io.netty.buffer.PoolThreadCache@f9f58cc]) 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 [io.netty.util.Recycler$1@267ec117]) and a value of type [io.netty.util.Recycler.Stack] (value [io.netty.util.Recycler$Stack@4bb6e0bf]) 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 [io.netty.util.Recycler$1@535d426e]) and a value of type [io.netty.util.Recycler.Stack] (value [io.netty.util.Recycler$Stack@fb46e84]) 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 [io.netty.util.internal.ThreadLocalRandom$2@ec3a42a]) and a value of type [io.netty.util.internal.ThreadLocalRandom] (value [io.netty.util.internal.ThreadLocalRandom@4e4ec8f8]) 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 [io.netty.util.Recycler$1@166c39f2]) and a value of type [io.netty.util.Recycler.Stack] (value [io.netty.util.Recycler$Stack@1b504a5e]) 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 [io.netty.util.Recycler$1@34426f54]) and a value of type [io.netty.util.Recycler.Stack] (value [io.netty.util.Recycler$Stack@759b0e99]) 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 [io.netty.util.concurrent.DefaultPromise$1@16db9b21]) 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 [io.netty.util.Recycler$1@166c39f2]) and a value of type [io.netty.util.Recycler.Stack] (value [io.netty.util.Recycler$Stack@2ba59f40]) 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 [io.netty.buffer.PooledByteBufAllocator$1@28ad6479]) and a value of type [io.netty.buffer.PoolThreadCache] (value [io.netty.buffer.PoolThreadCache@67a3923]) 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 [io.netty.util.Recycler$1@166c39f2]) and a value of type [io.netty.util.Recycler.Stack] (value [io.netty.util.Recycler$Stack@423d2c27]) 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 [io.netty.util.Recycler$1@535d426e]) and a value of type [io.netty.util.Recycler.Stack] (value [io.netty.util.Recycler$Stack@3e1dd66a]) 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 [io.netty.buffer.PooledByteBufAllocator$1@28ad6479]) and a value of type [io.netty.buffer.PoolThreadCache] (value [io.netty.buffer.PoolThreadCache@18e7e902]) 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.
我必须提到在取消部署应用程序时调用destroy()方法.如果我使用visualVM进行间谍活动,则在取消部署应用程序后,该线程仍处于活动状态.
public void destroy(){ try{ Statement statement = pgConnection.createStatement(); statement.addBatch("UNLISTEN xxxTest"); statement.executeBatch(); statement.close(); }catch(SQLException sqle) { sqle.printStackTrace(); } }
Neil McGuiga.. 5
为什么在这里需要休眠?只需使用JDBC。无论如何,您可能都希望触发应用程序范围的事件(例如,发送Websocket消息或释放ehcache),如果您需要进行休眠操作,请订阅该事件并使用Hibernate进行操作。
http://impossibl.github.io/pgjdbc-ng/是您的朋友。无需轮询。
看到http://blog.databasepatterns.com/2014/04/postgresql-nofify-websocket-spring-mvc.html
为什么在这里需要休眠?只需使用JDBC。无论如何,您可能都希望触发应用程序范围的事件(例如,发送Websocket消息或释放ehcache),如果您需要进行休眠操作,请订阅该事件并使用Hibernate进行操作。
http://impossibl.github.io/pgjdbc-ng/是您的朋友。无需轮询。
看到http://blog.databasepatterns.com/2014/04/postgresql-nofify-websocket-spring-mvc.html