Jsf 在PrimeFaces中通过p:dataTable进行更新后,BLOB图像仅显示在刷新页面上

Jsf 在PrimeFaces中通过p:dataTable进行更新后,BLOB图像仅显示在刷新页面上,jsf,tomcat,primefaces,jsf-2.2,graphicimage,Jsf,Tomcat,Primefaces,Jsf 2.2,Graphicimage,我正在一个上显示MySQL中以BLOB形式存储的图像,如下所示 <p:dataTable var="row" value="#{testManagedBean}" lazy="true" editable="true" rows="10"> <p:column headerText="id"> <h:outputText value="#{row.brandId}"/> </p:column> <p:

我正在一个
上显示MySQL中以BLOB形式存储的图像,如下所示

<p:dataTable var="row" value="#{testManagedBean}" lazy="true" editable="true" rows="10">
    <p:column headerText="id">
        <h:outputText value="#{row.brandId}"/>
    </p:column>

    <p:column headerText="Image">
        <p:cellEditor>
            <f:facet name="output">
                <p:graphicImage value="#{brandBean.image}" height="100" width="100">
                    <f:param name="id" value="#{row.brandId}"/>
                </p:graphicImage>
            </f:facet>
            <f:facet name="input">
                <p:graphicImage id="image" value="#{brandBean.image}" height="100" width="100">
                    <f:param name="id" value="#{row.brandId}"/>
                </p:graphicImage>
            </f:facet>
        </p:cellEditor>
    </p:column>

    <p:column headerText="Edit" width="50">
        <p:rowEditor/>
    </p:column>
</p:dataTable>
当通过单击数据表最后一列中的勾号(由
指示)来更新行(编辑后),就会调用
BrandBean
中的
getImage()
方法

这在使用PrimeFaces 5.0和JSF 2.2.6的GlassFish服务器4.0上运行的应用程序中是正确的

数据表(以及数据库)中的行更新后,新图像将立即显示在数据表中


另一个应用程序运行在Tomcat server 8.0.5上,使用Spring 4.0.0 GA,在更新数据表中的一行后,不会调用
getImage()
方法,从而在数据表中仍然显示旧图像(不是新更新的图像)(即使更改已正确传播到数据库)

仅当按F5刷新页面时(在大多数浏览器上),才会显示新更新的图像。在页面加载时,甚至不会显示新更新的图像(在地址栏中输入URL,然后按enter键)

换句话说,当通过单击
指示的勾号来更新数据表中的行时,不会调用
getImage()
方法(因此,不会从数据库中提取新图像以显示在
上)。仅当按F5快捷键刷新/重新加载页面时才会调用此方法


为什么会发生这种情况?如何在行更新后立即显示新更新的图像

表面上看,这不应该与Spring或JPA相关(在点击勾号后更新操作被正确地传播到数据库),而应该与Tomcat服务器相关

仅当按F5刷新页面时(在大多数浏览器上),才会显示新更新的图像。在页面加载时,甚至不会显示新更新的图像(在地址栏中输入URL,然后按enter键)

webbrowser正在缓存映像。资源通过响应标头中设置的缓存相关指令以每个URL为基础进行缓存。导致您的具体问题的原因是资源URL仍然相同,并且webbrowser不知道服务器端的资源已更改。详细说明了缓存(注意:过滤器不是此问题的解决方案)

基本上,您需要通过更改URL来强制webbrowser重新请求资源。对于这种情况,最常见的方法之一是在“上次修改”之后添加“上次修改”,即突然更改可缓存资源,并立即将其更改反映到所有客户端将图像的时间戳添加到URL的查询字符串。如果您使用的是JPA,那么应该这样做:

  • lastModified
    列添加到
    brand
    表中:

    ALTER TABLE brand ADD COLUMN lastModified TIMESTAMP DEFAULT now();
    
  • 使用适当的属性和设置该属性的属性扩展
    品牌
    实体:

    @Column @Temporal(TemporalType.TIMESTAMP)
    private Date lastModified;
    
    @PreUpdate
    public void onUpdate() {
        lastModified = new Date();
    }
    
    // +getter+setter
    
    (JPA在每次
    更新
    查询之前调用
    @PreUpdate
    带注释的方法)

  • 将其附加到图像URL(参数名称
    v
    是对“版本”的提示):

设计注意事项:如果图像不一定在每次更新
品牌时更新,则将其拆分到另一个表
图像
,并让
品牌
有一个FK(
@ManyToOne
@oone
)到
图像
。这也使属性成为“图像”可在webapp中的各种实体之间重用。

hy

我也有同样的问题,但是我的镜像src在硬盘中,而不是在DB中。 当我使用了一个随机数,但我不读它时,我就产生了这个问题。 一般来说,当这个参数是一个随机数时,我会在src映像中添加一个参数

我的解决方案如下:

public class UserPage {
  private String fotoCVPath;
  //all variabile
    private String getRandomImageName() {
        int i = (int) (Math.random() * 10000000);

        return String.valueOf(i);
    }
 public void editImage() {
//init the fotoCVPath
fotoCVPath = fotoCVPath + "?tmpVal=" + getRandomImageName();
}
  /**
     * @return the fotoCVPath <br>
     * 
     * @author  - asghaier <br>
     * 
     *         Created on 29/mag/2014
     */
    public String getFotoCVPath() {

        return fotoCVPath;
    }

    /**
     * @param fotoCVPath the fotoCVPath to set <br>
     * 
     * @author- asghaier <br>
     * 
     *         Created on 29/mag/2014
     */
    public void setFotoCVPath(String fotoCVPath) {
        this.fotoCVPath = fotoCVPath;
    }
}
<h:panelGrid ...al param >
    <h:column>
       <p:graphicImage id="imgCV" value="#{userPage.fotoCVPath}" styleClass="imgCVStyle" />
    </h:column>
</h:panelGrid>
公共类用户页{
私有字符串fotoCVPath;
//全可变
私有字符串getRandomImageName(){
int i=(int)(Math.random()*10000000);
返回字符串.valueOf(i);
}
public void editImage(){
//初始化fotoCVPath
fotoCVPath=fotoCVPath+“?tmpVal=“+getRandomImageName();
}
/**
*@返回fotoCVPath
* *@author-asghaier
* *创建于2014年6月29日 */ 公共字符串getFotocPath(){ 返回fotoCVPath; } /** *@param fotoCVPath要设置的fotoCVPath
* *@author-asghaier
* *创建于2014年6月29日 */ 公共void setFotoCVPath(字符串fotoCVPath){ this.fotoCVPath=fotoCVPath; } }
在你我的页面中,我有这样的元素graphicImage:

public class UserPage {
  private String fotoCVPath;
  //all variabile
    private String getRandomImageName() {
        int i = (int) (Math.random() * 10000000);

        return String.valueOf(i);
    }
 public void editImage() {
//init the fotoCVPath
fotoCVPath = fotoCVPath + "?tmpVal=" + getRandomImageName();
}
  /**
     * @return the fotoCVPath <br>
     * 
     * @author  - asghaier <br>
     * 
     *         Created on 29/mag/2014
     */
    public String getFotoCVPath() {

        return fotoCVPath;
    }

    /**
     * @param fotoCVPath the fotoCVPath to set <br>
     * 
     * @author- asghaier <br>
     * 
     *         Created on 29/mag/2014
     */
    public void setFotoCVPath(String fotoCVPath) {
        this.fotoCVPath = fotoCVPath;
    }
}
<h:panelGrid ...al param >
    <h:column>
       <p:graphicImage id="imgCV" value="#{userPage.fotoCVPath}" styleClass="imgCVStyle" />
    </h:column>
</h:panelGrid>

当我喜欢重新加载图像时,更新组件panelGrid

就我的例子来说,我有很多用处

<p:ajax event="click" onstart="PF('uploadImgCV').show();" update ="idPanelGrid"/>


我希望此模式能帮助您解决问题

也许您应该在tomcat邮件列表中询问此问题
<h:panelGrid ...al param >
    <h:column>
       <p:graphicImage id="imgCV" value="#{userPage.fotoCVPath}" styleClass="imgCVStyle" />
    </h:column>
</h:panelGrid>
<p:ajax event="click" onstart="PF('uploadImgCV').show();" update ="idPanelGrid"/>