Recuperar Imagen/PDF Salvo no Banco de dados

Pessoal, Bom dia

Quero fazer a visualização de um PDF salvo no banco porém não tenho a mínima idéia de como fazer…

Eu gostaria de fazer da seguinte forma:
Tenho a listagem dos documentos salvos no banco de dados, onde consigo fazer edição e exclusão das informações.

Eu gostaria de colocar mais um botão na ultima coluna ao lado de editar e excluir, onde ao clicar abre uma modal visualizando o PDF salvo.

Vou listar abaixo o procedimento que fiz para salvar no banco…

1.Tabela

package modelo;

import java.io.Serializable;
import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.ManyToOne;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;

@Entity
public class ParceiroNegocioDocumentos implements Serializable {

private static final long serialVersionUID = 1L;

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Lob
private byte[] documento;

@Column
private String documentoNome;

@Column
private Long documentoTamanho;

@Temporal(TemporalType.DATE)
private Date dataVencimento;

@Column(length= 100)
private String orgao;

@Column
private String descricao;

@Column(length= 100)
private String inclusaoUsuarioNome; //Optou-se por uma string, devido a possibilidade de alterar a descricao do usuario, dessa forma fica a descrição do usuario no dia da inclusão;

@Temporal(TemporalType.DATE)
private Date inclusaoData;

@Column(length= 100)
private String alteracaoUsuarioNome; //Optou-se por uma string, devido a possibilidade de alterar a descricao do usuario, dessa forma fica a descrição do usuario no dia da inclusão;

@Temporal(TemporalType.DATE)
private Date alteracaoData;

@ManyToOne
private ParceiroNegocio parceiroNegocio;

@ManyToOne
private Usuario usuario;

@Transient
@Temporal(TemporalType.DATE) //Utilização na pesquisa -- não vai para o BD
private Date dtInicial;
@Transient
@Temporal(TemporalType.DATE) // Utilização na pesquisa -- não vai para o BD
private Date dtFinal;


public Long getId() {
	return id;
}
public void setId(Long id) {
	this.id = id;
}
public byte[] getDocumento() {
	return documento;
}
public void setDocumento(byte[] documento) {
	this.documento = documento;
}
public String getDocumentoNome() {
	return documentoNome;
}
public void setDocumentoNome(String documentoNome) {
	this.documentoNome = documentoNome;
}
public Long getDocumentoTamanho() {
	return documentoTamanho;
}
public void setDocumentoTamanho(Long documentoTamanho) {
	this.documentoTamanho = documentoTamanho;
}
public Date getDataVencimento() {
	return dataVencimento;
}
public void setDataVencimento(Date dataVencimento) {
	this.dataVencimento = dataVencimento;
}
public String getOrgao() {
	return orgao;
}
public void setOrgao(String orgao) {
	this.orgao = orgao;
}
public String getDescricao() {
	return descricao;
}
public void setDescricao(String descricao) {
	this.descricao = descricao;
}
public String getInclusaoUsuarioNome() {
	return inclusaoUsuarioNome;
}
public void setInclusaoUsuarioNome(String inclusaoUsuarioNome) {
	this.inclusaoUsuarioNome = inclusaoUsuarioNome;
}
public Date getInclusaoData() {
	return inclusaoData;
}
public void setInclusaoData(Date inclusaoData) {
	this.inclusaoData = inclusaoData;
}
public String getAlteracaoUsuarioNome() {
	return alteracaoUsuarioNome;
}
public void setAlteracaoUsuarioNome(String alteracaoUsuarioNome) {
	this.alteracaoUsuarioNome = alteracaoUsuarioNome;
}
public Date getAlteracaoData() {
	return alteracaoData;
}
public void setAlteracaoData(Date alteracaoData) {
	this.alteracaoData = alteracaoData;
}
public ParceiroNegocio getParceiroNegocio() {
	return parceiroNegocio;
}
public void setParceiroNegocio(ParceiroNegocio parceiroNegocio) {
	this.parceiroNegocio = parceiroNegocio;
}
public Usuario getUsuario() {
	return usuario;
}
public void setUsuario(Usuario usuario) {
	this.usuario = usuario;
}
public Date getDtInicial() {
	return dtInicial;
}
public void setDtInicial(Date dtInicial) {
	this.dtInicial = dtInicial;
}
public Date getDtFinal() {
	return dtFinal;
}
public void setDtFinal(Date dtFinal) {
	this.dtFinal = dtFinal;
}

@Override
public int hashCode() {
	final int prime = 31;
	int result = 1;
	result = prime * result + ((id == null) ? 0 : id.hashCode());
	return result;
}
@Override
public boolean equals(Object obj) {
	if (this == obj)
		return true;
	if (obj == null)
		return false;
	if (getClass() != obj.getClass())
		return false;
	ParceiroNegocioDocumentos other = (ParceiroNegocioDocumentos) obj;
	if (id == null) {
		if (other.id != null)
			return false;
	} else if (!id.equals(other.id))
		return false;
	return true;
}

////////////////////////////////
//		    Marcadores        //
////////////////////////////////


@Transient
public boolean NovoCadastro() {
	return getId() == null;
}

@Transient
public boolean isEditando() {
	return !this.NovoCadastro();
}

@Transient
public boolean NaoEditando() {
	return !this.isEditando();
}        
}
  1. *.xhtml

     <p:outputLabel value="Documento" />
     		<h:form enctype="multipart/form-data">
     			<p:fileUpload style="margin-top: 20px"
     				fileUploadListener="#{parceiroNegocioDocumentosBean.upload}"
     				allowTypes="/(\.|\/)(pdf)$/" 
     				invalidFileMessage="Formato de arquivo inválido" multiple="false"
     				mode="advanced">
     				
     			</p:fileUpload>
     			<p:growl id="messages" showDetail="true" />
     		</h:form>
    
  2. ManagedBean Upload

       private ParceiroNegocioDocumentos pn_documentos;
    
       public void upload(FileUploadEvent event) {
    
     
        // Cria um arquivo UploadFile, para receber o arquivo do evento
        UploadedFile arq = event.getFile();
        // Transformar a imagem em bytes para salvar em banco de dados
        byte[] bimagem = event.getFile().getContents();
        pn_documentos.setDocumento(bimagem);
        pn_documentos.setDocumentoNome(arq.getFileName());
        pn_documentos.setDocumentoTamanho(arq.getSize());
             
     pn_documentosService.salvar(pn_documentos);
     }
    
  3. Service

    package service;
     
    import java.io.Serializable;
    
    import javax.inject.Inject;
    
    import modelo.ParceiroNegocioDocumentos;
    import repository.ParceiroNegocioDocumentosRepository;
    import security.Seguranca;
    
    public class ParceiroNegocioDocumentosService implements Serializable {
    
    private static final long serialVersionUID = 1L;
    
    @Inject
    private ParceiroNegocioDocumentosRepository pn_documentosRepository;
    @Inject
    private Seguranca seguranca;
     
    public ParceiroNegocioDocumentos salvar(ParceiroNegocioDocumentos pn_documentos) {	pn_documentos.setUsuario(seguranca.getUsuario());
     	
     return pn_documentosRepository.guardar(pn_documentos);
      }
    }
    
  4. Repository

    public ParceiroNegocioDocumentos guardar(ParceiroNegocioDocumentos pn_documentos) {
     		
     if (pn_documentos.isEditando()) {
     	FacesUtil.addInfoMessage("Documento atualizado com sucesso!");
     	pn_documentos.setAlteracaoData(new Date());
     	pn_documentos.setAlteracaoUsuarioNome(seguranca.getNomeUsuario());
     	
     }else {
     	FacesUtil.addInfoMessage("Documento cadastrado com sucesso!");
     	
     	pn_documentos.setInclusaoData(new Date());
     	pn_documentos.setInclusaoUsuarioNome(seguranca.getNomeUsuario());
     	
     }
     
     
     if (pn_documentos.getOrgao() != null) {
     	pn_documentos.setOrgao(pn_documentos.getOrgao().toUpperCase());
     }
     if(pn_documentos.getDescricao() != null) {
     	pn_documentos.setDescricao(pn_documentos.getDescricao().toUpperCase());
     }
     
     
     return manager.merge(pn_documentos);
     }