标准用例--您需要一个器,以便在每次更新/插入/删除时执行一些代码。例如,用于审计。但是,如果您需要侦听器中的Spring依赖,并且您正在使用JPA,那么事情就不那么简单了。

首先,只有侦不够的JPA可以用@PreUpdate对方法进行注释,但上下文中最多的是它所涉及的实体能需要旧的价值观。或实体的提取ID。或者其他元数据。所有这些都不为JPA所支持。因此,您需要实现Hibernate接口,如PreDeleteEventListener、PreUpdateEventListener、PostInsertEventListener等,并获取它们的XEvent对象。

但是如果您使用的是JPA,那么您很难让这些监听器实现Spring管理和注册。您可以将它们作为类名列出,但是Hibernate会实例化它们。下面是您需要进行的调整,以使此工作正常进行:

首先,扩展持久性提供程序:

public class HibernateExtendedPersistenceProvider extends HibernatePersistence {
private PostInsertEventListener[] postInsertEventListeners;
private PreUpdateEventListener[] preUpdateEventListeners;
private PreDeleteEventListener[] preDeleteEventListeners;
 
@SuppressWarnings("rawtypes")
@Override
public EntityManagerFactory createEntityManagerFactory(String persistenceUnitName, Map properties) {
Ejb3Configuration cfg = new Ejb3Configuration();
setupConfiguration(cfg);
Ejb3Configuration configured = cfg.configure( persistenceUnitName, properties );
return configured != null ? configured.buildEntityManagerFactory() : null;
}
@SuppressWarnings("rawtypes")
@Override
public EntityManagerFactory createContainerEntityManagerFactory(PersistenceUnitInfo info, Map properties) {
Ejb3Configuration cfg = new Ejb3Configuration();
setupConfiguration(cfg);
Ejb3Configuration configured = cfg.configure( info, properties );
return configured != null ? configured.buildEntityManagerFactory() : null;
}
 
private void setupConfiguration(Ejb3Configuration cfg) {
cfg.getEventListeners().setPostInsertEventListeners(postInsertEventListeners);
cfg.getEventListeners().setPreDeleteEventListeners(preDeleteEventListeners);
cfg.getEventListeners().setPreUpdateEventListeners(preUpdateEventListeners);
//TODO if others are needed - add them
}
public void setPostInsertEventListeners(PostInsertEventListener[] postInsertEventListeners) {
this.postInsertEventListeners = postInsertEventListeners;
}
public void setPreUpdateEventListeners(PreUpdateEventListener[] preUpdateEventListeners) {
this.preUpdateEventListeners = preUpdateEventListeners;
}
public void setPreDeleteEventListeners(PreDeleteEventListener[] preDeleteEventListeners) {
this.preDeleteEventListeners = preDeleteEventListeners;
}
}

然后用@Component注释侦听器(或者按照您喜欢的方式将它们声明为Springbean)。然后登记:

<bean id="hibernatePersistenceProvider" class="com.foo.bar.configuration.HibernateExtendedPersistenceProvider">
<property name="postInsertEventListeners">
<list>
<ref bean="hibernateAuditLogListener" />
</list>
</property>
<property name="preUpdateEventListeners">
<list>
<ref bean="hibernateAuditLogListener" />
</list>
</property>
<property name="preDeleteEventListeners">
<list>
<ref bean="hibernateAuditLogListener" />
</list>
</property>
</bean>

最后,将自定义持久性提供程序设置为实体管理器工厂bean:

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceProvider" ref="hibernatePersistenceProvider" />

你刚才做的事:

  • 利用PersistenceProvider允许您获得Hibernate配置对象这一事实,在使用JPA时无法访问该配置对象
  • 将侦听器注册为Springbean,并将它们添加到扩展持久性提供程序,后者将它们注册为Hibernate。
  • 设置Spring的LocalContainerEntityManagerFactoryBean的“PersistenceProvider”属性。通常您不会设置它,因为它是从供应商适配器或类路径推断出来的。

https://www.imdb.com/list/ls550567867/

有一天,我意识到我的Tomcat默认使用块传输编码(HTTP1.1)。我不知道其他的服务器/容器/框架/语言,但是用块发送页面并不少见,比如Facebook就这样做了。“分块”的意思是服务器发送它已经准备好的页面片段,以便浏览器在服务器处理下一个块时呈现它们。

在JSP(可能在许多其他视图技术中)中有一个缓冲区--每当缓冲区被填充时,它就会被刷新到客户端。这意味着所有的头和第一个信息块(即缓冲区的内容)一起被发送。

但是有一个警告--如果服务器处理第二个(或任何后续)块时发生错误,会发生什么?您可能希望服务器将错误页发送到浏览器,但它不能这样工作:

  • 您不能重定向(发送位置标头),因为标题和响应状态已经发送。(你不能,当然服务器不能)
  • 您不能进行服务器端重定向(前进),因为新页面必须在已经发送的部分之后呈现--它看起来肯定很难看。

我想知道该怎么办,便堆积如山。显然,没有什么好办法摆脱这种局面。我所做的就是将这个片段发送到浏览器,然后浏览器重定向到错误页面:

</script><script>window.href.location="errorPage"</script>

特别是在JSP中是如何做到这一点的:<%@ page errorPage="/error/redirector.jsp" %>,并且redirector.jsp包含上面的脚本标记。为什么我们要从结束脚本标签开始呢?可能已经呈现的块中有一个打开的脚本标记,所以我们必须关闭它。丑陋,我知道,但似乎没有别的办法。

另一个问题出现了--我们这里是否需要分块的编码,难道它不适合下载的大型文件吗?这是一个单独的讨论,但由于Tomcat使用它作为默认的传输-编码,而Fa