broken pipe
导致broken pipe的原因有很多,不过其根本原因都是:当往socket管道写入数据的时候,管道已经关闭。某次查生产问题的时候,发现日志中有很多booken pipe的错误,都发生在当服务器向客户端返回页面内容的情况下。
java.io.IOException: Broken pipe
导致这个错误的主要原因是,当浏览器发起请求,服务端处理时间较长,在服务端还没有返回响应内容的时候,浏览器端就断开了连接(关闭浏览器,删除iframe等)。
- 所以正常情况下出现这个问题,其实并不影响业务的运行
hibernate set 自动更新
//执行完之后,数据库中该用户的名称会被修改成newName
UserDTO user = userDao.findUserByCode("userCode");
user.setUserName("newName");
相信很多人都碰到过这个问题,当对hibernate查询出来的某个实体类进行set
操作的时候,即使没有调用 update
方法,这个值也会被更新到数据库中。
不过也不是每次进行set
操作就一定会被更新到数据库。必须满足Hibernate session
的 FlushMode
为AUTO
,COMMIT
,ALWAYS
状态。如果FlushMode
为NEVEL
或者MANUAL
,那么该 set
操作就不会被更新到数据库。而spring的非readOnly事务
则会修改Hibernate session
的 FlushMode
为AUTO
。
假设spring事务配置
如下:
<bean id="autoproxy" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames">
<list>
<value>*Service</value>
</list>
</property>
<property name="interceptorNames">
<list>
<value>transactionInterceptor</value>
</list>
</property>
</bean>
上述配置表示所有以Service结尾的bean都会生成事务代理类
<bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
<property name="transactionManager">
<ref bean="transactionManager" />
</property>
<!-- 配置事务属性 -->
<property name="transactionAttributes">
<props>
<prop key="save*">PROPAGATION_REQUIRED</prop>
<prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
</bean>
上述配置表示find
开头的方法是readOnly
模式,此时hibernate session
对应的FlushMode
为MANUAL
。save
开头的方法对应的FlushMode
为AUTO
。
- newName会更新到数据库
UserDTO user = userDao.findUserByCode("userCode");
user.setUserName("newName");
xxxService.saveSomething();
- newName不会更新到数据库
UserDTO user = userDao.findUserByCode("userCode");
user.setUserName("newName");
xxxService.findSomething();
在使用struts的时候,通常我们会设置异常拦截器:
<interceptors>
<interceptor name="ExceptionInterceptor" class="com.xxx.ExceptionInterceptor">
</interceptor>
</interceptors>
异常拦截器中除了会有记录日志,发送邮件报警以外,也有把异常信息保存到数据库的情况:
ExceptionService.saveExceptionInfo(e.getMessage());
那么此时 hibernate session
的FlushMode
就会被设置为AUTO
,导致对DTO的set操作会被保存到数据库。
总结
当你在Action中执行hibernate查询操作,并且对查询出来的hibernate实体类进行set操作修改值的时候,如果此时,前端关闭了浏览器,导致服务端抛出broken pipe错误,进入struts异常拦截器,把错误信息记录到数据库,导致将hibernate session
的FlushMode
变成了 AUTO
,此时set
的新值就会被更新到数据库,从而导致其他业务问题。