由于每个实体都有BLOB字段,我的Java应用程序变得非常慢。该字段通常用于存储PDF文件,每当我必须列出所有对象时,都需要相当长的时间,直到持久性提供程序可以完成其工作。我寻找有关如何处理此类数据的答案,但其中一些人谈到将BLOB存储在单独的表中,然后使用FetchType.LAZY.是否有任何方法仅在需要时获取此字段而无需创建另一个表?如果没有,创建另一个表是最合适的解决方案吗?
实体代码
@Cache(alwaysRefresh = true)
public class ScdDocumento implements Serializable, MultipleSelector {
@Transient
public static final String QUERY_RELATORIO_DOC_LOC = "consultas/ctrl_docs/consulta_relatorio_doc_local.txt";
@Transient
public static final String QUERY_RELATORIO_DOC_GRUPO = "consultas/ctrl_docs/consulta_relatorio_doc_grupo.txt";
@Id
@Column(name = "nome", length = 50)
private String nome;
@Column(name = "revisao")
private int revisao;
@Column(name = "id_tipo")
private int id_tipo;
@Column(name = "situacao", length = 1)
private String situacao;
@Column(name = "doc_blob_nome", length = 50)
private String doc_blob_nome;
@Lob
@Basic(fetch = FetchType.LAZY)
@Column(name = "documento_blob", nullable = false)
private byte[] documento_blob; //The field that impacts the application perfomance
@Column(name = "abrangencia_geral")
private int abrangencia_geral;
@ManyToMany
@JoinTable(name = "SCD_DOC_GRUPO", joinColumns = {@JoinColumn(name = "id_doc")},
inverseJoinColumns = {@JoinColumn(name = "id_grupo")})
private Set<SosGrupo> grupos;
@ManyToOne
@JoinColumn(name = "id_tipo", insertable = false, updatable = false)
private ScdTipo tipo;
@ManyToMany
@JoinTable(name = "SCD_REFERENCIA", joinColumns = {@JoinColumn(name = "doc_pai")},
inverseJoinColumns = {@JoinColumn(name = "doc_filho")})
private Set<ScdDocumento> referencias;
@ManyToMany
@JoinTable(name = "SCD_REFERENCIA", joinColumns = {@JoinColumn(name = "doc_filho")},
inverseJoinColumns = {@JoinColumn(name = "doc_pai")})
private Set<ScdDocumento> referenciadoPor;
@ManyToMany
@JoinTable(name = "SCD_PALAVRA_REFERENCIA", joinColumns = {@JoinColumn(name = "documento")},
inverseJoinColumns = {@JoinColumn(name = "palavra")})
private Set<ScdPalavraChave> palavrasChaves;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "documento")
private Set<ScdOrdem> ordens;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "documento")
private Set<ScdArquivoOs> arquivosOs;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "documento")
private Set<ScdArquivoHistorico> arquivosHistorico;
@ManyToMany(cascade = {CascadeType.REFRESH, CascadeType.MERGE})
@JoinTable(name = "SCD_LOCAL_DOC", joinColumns = {@JoinColumn(name = "id_doc")},
inverseJoinColumns = {@JoinColumn(name = "id_local")})
private Set<ScdLocal> locais;
@Override
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public int getRevisao() {
return revisao;
}
public void setRevisao(int revisao) {
this.revisao = revisao;
}
public int getIdTipo() {
return id_tipo;
}
public void setIdTipo(int id_tipo) {
this.id_tipo = id_tipo;
}
public String getSituacao() {
return situacao;
}
public void setSituacao(String situacao) {
this.situacao = situacao;
}
public String getDocBlobNome() {
return doc_blob_nome;
}
public void setDocBlobNome(String doc_blob_nome) {
this.doc_blob_nome = doc_blob_nome;
}
public byte[] getDocumentoBlob() {
return documento_blob;
}
public void setDocumentoBlob(byte[] documento_blob) {
this.documento_blob = documento_blob;
}
public int getAbrangenciaGeral() {
return abrangencia_geral;
}
public void setAbrangenciaGeral(int abrangencia_geral) {
this.abrangencia_geral = abrangencia_geral;
}
public Set<SosGrupo> getGrupos() {
return grupos;
}
public void setGrupos(Set<SosGrupo> grupo) {
this.grupos = grupo;
}
public ScdTipo getTipo() {
return tipo;
}
public void setTipo(ScdTipo tipo) {
this.tipo = tipo;
}
public Set<ScdDocumento> getReferencias() {
return referencias;
}
public void setReferencias(Set<ScdDocumento> referencias) {
this.referencias = referencias;
}
public Set<ScdDocumento> getReferenciadoPor() {
return referenciadoPor;
}
public void setReferenciadoPor(Set<ScdDocumento> referenciadoPor) {
this.referenciadoPor = referenciadoPor;
}
public Set<ScdPalavraChave> getPalavrasChaves() {
return palavrasChaves;
}
public void setPalavrasChaves(Set<ScdPalavraChave> palavrasChaves) {
this.palavrasChaves = palavrasChaves;
}
public Set<ScdOrdem> getOrdens() {
return ordens;
}
public void setOrdens(Set<ScdOrdem> ordens) {
this.ordens = ordens;
}
public Set<ScdArquivoOs> getArquivosOs() {
return arquivosOs;
}
public void setArquivosOs(Set<ScdArquivoOs> arquivosOs) {
this.arquivosOs = arquivosOs;
}
public Set<ScdArquivoHistorico> getArquivosHistorico() {
return arquivosHistorico;
}
public void setArquivosHistorico(Set<ScdArquivoHistorico> arquivosHistorico) {
this.arquivosHistorico = arquivosHistorico;
}
public Set<ScdLocal> getLocais() {
return locais;
}
public void setLocais(Set<ScdLocal> locais) {
this.locais = locais;
}
@Override
public String getIdRef() {
return nome;
}
@Override
public String getDesc() {
return tipo.getNome();
}
}
导致问题的方法
图像使用者界面
private void loadDocumentTable(String situacao) {
mapaDocumentos = new TreeMap<>();
modelDocumentos.setRowCount(0);
docdao.getCriteria("situacao", situacao).forEach((e) -> {
mapaDocumentos.put(e.getNome(), e);
});
mapaDocumentos.entrySet().forEach((e) -> {
String desc = e.getValue().getDocBlobNome();
modelDocumentos.addRow(new Object[]{e.getKey(), desc.substring(0, desc.length() - 3), e.getValue().getRevisao()});
});
}
通用刀
@Override
public List<T> getCriteria(String column, Object value){
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<T> cq = cb.createQuery(clazz);
Root<T> root = cq.from(clazz);
EntityType<T> ent = root.getModel();
cq.where(cb.equal(root.get(ent.getSingularAttribute(column)), value.toString()));
return em.createQuery(cq).getResultList();
}
表模型
坚持
将此添加到我的持久性.xml,但 eclipselink 仍然急切地获取 byte[] 字段。
Maven插件
<plugin>
<groupId>de.empulse.eclipselink</groupId>
<artifactId>staticweave-maven-plugin</artifactId>
<version>1.0.0</version>
<executions>
<execution>
<phase>process-classes</phase>
<goals>
<goal>weave</goal>
</goals>
<configuration>
<persistenceXMLLocation>META-INF/persistence.xml</persistenceXMLLocation>
<logLevel>FINE</logLevel>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.jpa</artifactId>
<version>2.5.2</version>
</dependency>
</dependencies>
</plugin>
最终编辑
staticweave-maven-plugin实际上是有效的,但每次我更改某些内容时都需要构建项目以提高性能。发生这种情况是因为编织是静态的,所以它是在构建时应用的,而不是在使用IDE运行项目时应用的。
JPA基础还允许指定LAZY的提取类型,这将阻止加载BLOB,直到您在实体中访问它。OneToOne、ManyToOne和basic映射需要对您的实体进行字节码增强,以便EclipseLink在您访问一个惰性属性并加载它时获得通知,这在这里被描述为编织。这将确保它在默认情况下不会被加载。
通过使用编织,您还可以使用实体图来指定加载什么以及何时加载。这可以允许在使用blob时将blob与实体的其余部分一起加载到单个查询中,并在默认情况下将其排除在其他地方。看看JPA实体图的获取和加载有什么区别?有关加载和获取图形的信息。
我从http://docs.oracle.com/javaee/7/tutorial/doc/servlets012.htm Java EE为servlet和过滤器提供异步处理支持。如果servlet或过滤器在处理请求时达到潜在的阻塞操作,它可以将该操作分配给异步执行上下文,并将与请求相关联的线程立即返回到容器,而不生成响应。阻塞操作在不同线程的异步执行上下文中完成,该线程可以生成响应或将请求分派
问题内容: 在代码底部运行的示例需要很长时间才能在我的机器上解决: 这是代码: 每只只供三只骆驼。我想至少这样做4次。该测试用例仍在运行(现在:()已经大约5分钟了。如果完成,我将对其进行更新。 我应该怎么做才能改善这段代码?(通常以性能为依据,但也欢迎其他建议)。 问题答案: 我以前也被这个绊倒了。这里的瓶颈实际上是。 该in语句是如此易于使用,你忘记了它是线性搜索,而当你在列表上进行线性搜索时
问题内容: 我有一个数据模型,该数据模型在一个实体和其他11个实体之间具有一对多关系。这12个实体一起代表一个数据包。我遇到的问题是与这些关系的“许多”方面发生的插入次数有关。其中一些可以具有多达100个单独的值,因此要将一个完整的数据包保存在数据库中,最多需要500次插入。 我正在将MySQL 5.5与InnoDB表一起使用。现在,通过测试数据库,我发现在处理批量插入时,它每秒可以轻松地每秒进行
我第一次使用spring batch应用程序,由于框架太灵活了,我有几个关于性能和实现作业的最佳实践的问题,在spring文档中找不到明确的答案。 > 读取由第三方以先前指定的布局发送的具有固定列长值的ASCII文件(第1步读取器) 在oracle数据库上写入有效行(第1步写入器) 执行前一步后,使用第1步的finish时间戳更新数据库中的表(第2步tasklet) 当作业停止时,发送一封电子邮件
我有一个名为Emails的列族,我正在将邮件保存到这个CF中,编写5000封邮件需要100秒。 我使用的是i3处理器,8gb内存。我的数据中心有6个节点,复制因子=2。 我们存储在卡桑德拉中的数据大小会影响性能吗?影响写入性能的所有因素是什么,如何提高性能? 预先感谢..
我们正在快速开发一个应用程序,其中我们需要一次获取超过50K行(在应用程序加载时执行),然后数据将用于应用程序的其他部分进行进一步计算。我们正在使用Firebase实时数据库,我们面临一些严重的性能问题。 它目前需要大约40秒才能加载50K行(目前使用的是免费数据库版本,不确定这是否是原因),但我们也观察到,当多个用户使用该应用程序时,加载50K行开始需要大约1分20秒,Peak达到100%。 您