Как повысить производительность в EclipseLink при работе с полями BLOB? - PullRequest
0 голосов
/ 04 июня 2018

Мое Java-приложение стало очень медленным из-за поля BLOB, которое есть у каждого объекта.Это поле обычно используется для хранения файла 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();
    }
}

Методы, вызывающие проблему

GUI

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();
}

Настольная модель

enter image description here

Постоянство

Добавил это в мой файл persistence.xml, но eclipselink все еще с нетерпением извлекал поле byte [].

enter image description here

Плагин 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-фактически работает, но мне нужноСоздавайте проект каждый раз, когда я что-то меняю, чтобы повысить производительность.Это происходит потому, что переплетение является статическим, поэтому оно применяется во время сборки, а не при запуске проекта с использованием IDE.

1 Ответ

0 голосов
/ 04 июня 2018

JPA основы также позволяют указывать тип выборки LAZY, что будет препятствовать загрузке BLOB-объекта до тех пор, пока вы не получите доступ к нему в объекте.OneToOne, ManyToOne и базовые сопоставления требуют улучшения байт-кода ваших сущностей для EclipseLink, чтобы получать уведомление при доступе к атрибуту lazy и загружать его, который здесь описывается как переплет .Это гарантирует, что он не загружается по умолчанию.

С помощью ткачества вы также можете использовать графы сущностей , чтобы указать, что загружается и когда.Это может позволить загрузить большой двоичный объект в одном запросе с остальной частью объекта, когда он будет использоваться, и исключить его по умолчанию в другом месте.См. В чем разница между FETCH и LOAD для графа сущностей JPA? для получения информации о графиках загрузки и выборки.

...