Hibernate gravando Blob no oracle

7 respostas
W

Eai pessoal alguem sabe como gravar uma array de byte[] em um campo BLOB no oracle?

Estou implementando um solucao do site do hibernate q é:

1- implementar um userType

import java.sql.PreparedStatement; 
import java.sql.ResultSet; 
import java.sql.SQLException; 
import java.sql.Types; 
import java.sql.Blob; 

import cirrus.hibernate.Hibernate; 
import cirrus.hibernate.HibernateException; 
import cirrus.hibernate.UserType; 

public class BinaryBlobType implements UserType 
{ 
  public int[] sqlTypes() 
  { 
    return new int[] { Types.BLOB }; 
  }

  public Class returnedClass() 
  { 
    return byte[].class; 
  } 

  public boolean equals(Object x, Object y) 
  { 
    return (x == y) 
      || (x != null 
        && y != null 
        && java.util.Arrays.equals((byte[]) x, (byte[]) y)); 
  } 

  public Object nullSafeGet(ResultSet rs, String[] names, Object owner) 
  throws HibernateException, SQLException 
  { 
    Blob blob = rs.getBlob(names[0]); 
    return blob.getBytes(1, (int) blob.length()); 
  } 

  public void nullSafeSet(PreparedStatement st, Object value, int index) 
  throws HibernateException, SQLException 
  { 
    st.setBlob(index, Hibernate.createBlob((byte[]) value)); 
  } 

  public Object deepCopy(Object value) 
  { 
    if (value == null) return null; 

    byte[] bytes = (byte[]) value; 
    byte[] result = new byte[bytes.length]; 
    System.arraycopy(bytes, 0, result, 0, bytes.length); 

    return result; 
  } 

  public boolean isMutable() 
  { 
    return true; 
  } 

}

2 - o meu bean ficaria assim:

public class ImageValue
{
  private long id;
  private image byte[];

  public long getId() { return id; }
  public void setId(long id) { this.id = id; }

  public byte[] getImage() { return image; }
  public void setImage(byte[] image) { this.image = image; }
}

e no meu xml(hbm) ficaria assim:

<class name="ImageValue" table="IMAGE_VALUE">
  <id name="id/>
  <property name="image" column="IMAGE" type="mypackage.BinaryBlobType"/>
</class>

só q usando essa implementação esta me gerando um erro:

java.lang.ClassCastException
	oracle.jdbc.driver.OraclePreparedStatement.setBlob(OraclePreparedStatement.java:2094)
	org.apache.commons.dbcp.DelegatingPreparedStatement.setBlob(DelegatingPreparedStatement.java:260)
	org.apache.commons.dbcp.DelegatingPreparedStatement.setBlob(DelegatingPreparedStatement.java:260)
	br.gov.dpf.mpgo.util.BinaryBlobType.nullSafeSet(BinaryBlobType.java:159)
	net.sf.hibernate.type.CustomType.nullSafeSet(CustomType.java:118)
	net.sf.hibernate.persister.EntityPersister.dehydrate(EntityPersister.java:394)
	net.sf.hibernate.persister.EntityPersister.insert(EntityPersister.java:512)
	net.sf.hibernate.persister.EntityPersister.insert(EntityPersister.java:489)
	net.sf.hibernate.impl.ScheduledInsertion.execute(ScheduledInsertion.java:28)
	net.sf.hibernate.impl.SessionImpl.executeAll(SessionImpl.java:2306)
	net.sf.hibernate.impl.SessionImpl.execute(SessionImpl.java:2259)
	net.sf.hibernate.impl.SessionImpl.flush(SessionImpl.java:2185)
	net.sf.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:61)
	br.gov.dpf.mpgo.dao.hibernate.HibernateDAOFactory.transactionCommit(HibernateDAOFactory.java:128)
	br.gov.dpf.mpgo.dao.hibernate.DAOHibernateAbstract.insert(DAOHibernateAbstract.java:30)
	br.gov.dpf.mpgo.action.ActionCadastroImagem.gravarImagem(ActionCadastroImagem.java:47)
	sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	java.lang.reflect.Method.invoke(Method.java:324)
	org.apache.struts.actions.DispatchAction.dispatchMethod(DispatchAction.java:280)
	org.apache.struts.actions.DispatchAction.execute(DispatchAction.java:216)
	org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:484)
	org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:274)
	org.apache.struts.action.ActionServlet.process(ActionServlet.java:1482)
	org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:525)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:810)

tb fiz uma modificacao no objeto BinaryBlobType no metodo nullSafeSet:

public void nullSafeSet(PreparedStatement st, Object value, int index) 
  throws HibernateException, SQLException 
  { 
     st.setBytes(index, (byte[]) value); 
  }

com isso eu consigo gravar uma array de byte[] pequena na ordem de 4kb

ja tentei um monte de coisa e nada.
alguem ja passou por isso ou tem alguma ideia de implementacao?

7 Respostas

T

É problema com o driver do Oracle.

Veja a solução aqui:

http://www.hibernate.org/73.html

W

valeu velhinho pela dica, vc sabe qual drive usar??

T

Não é problema de versão do driver… O driver da Oracle, não importa a versão, ainda está com algum bug (daquele tipo que eles desistem de consertar, porque muita gente já escreveu código que supõe que o driver está com defeito mesmo. É o tipo “this is not a bug - it’s a feature” ou do tipo “this will not be fixed, it’s by design”.)
Mas se for o caso use o classes12.zip (ou classes12.jar) mais novo que vier com sua instalação do Oracle.
Isso é muito chato, porque se você já viu a definição formal do JDBC, vai ter a nítida impressão que as pessoas que definiram o JDBC fizeram-no com base no Oracle, e depois é que generalizaram para outros bancos de dados. A terminologia para muitas coisas no JDBC é igual à do Oracle (por exemplo, BLOB no Oracle e no JDBC é IMAGE no SQL Server e Sybase).

W

eu sei q nessa não deve ser a melhor forma de se fazer isso, porem ela e funcional

eu insiro um blob fazio usando uma função do Orable “empty_blob”

public void insert(TbMapasfoto o) throws Exception {
	    byte[] foto = o.getBiImagem();
	    o.setBiImagem(new byte[0]);
	    super.insert(o);	
	    insertBlob(o.getCdMapasfotos(), foto);
	}

depois eu faço um “select for update” para inserir o meu blob

private void insertBlob(Integer pk, byte[] arrayByte) throws Exception {
	    Session s = HibernateDAOFactory.getSession();
	    Connection conn =  s.connection();    
	    String sqlLockRow = "SELECT BI_IMAGEM FROM TB_MAPASFOTOS WHERE CD_MAPASFOTOS = "+  pk +" FOR UPDATE";
	    PreparedStatement st = conn.prepareStatement(sqlLockRow);    
	    ResultSet r = st.executeQuery();
	    oracle.sql.BLOB b = null;
		while (r.next()) {
			b = (oracle.sql.BLOB) r.getBlob(1);
		}
		r.close();

		// Updates blob.
		OutputStream os = b.getBinaryOutputStream();
		
		ByteArrayInputStream is = new ByteArrayInputStream(arrayByte);
		
		byte[] buffer = new byte[b.getBufferSize()];
		
		int bytesRead = 0;
		
		while ((bytesRead = is.read(buffer)) != -1)
			os.write(buffer, 0, bytesRead);
		os.close();
		is.close();
	    conn.commit();    
	    st.close();
	    conn.close();
	  
	}
ynaue

Oie!!
Voce conseguiu ???
Se sim tem como me ajudar???
Eu tb quero gravar um dado do tipo Blob e uso hibernate só que nem sei por onde começar.

Obrigada

fiaux

No hibernate a gente usa Hibernate.createBlob() passando um array de bytes.
Sobre não conseguir gravar mais de 4kb, eu já tive isso e atualizei o driver.

T
Mesmo trocando o drive classes12 para o ojdbc14, Tive que implementar a seguinte classe para persistir no objeto.

public static Blob getBlobOracle(InputStream inputStream) throws Throwable {

oracle.sql.BLOB blob;

try{

blob =  oracle.sql.BLOB.createTemporary(HbnUtil.getCurrentSession().connection(),

false, oracle.sql.BLOB.DURATION_SESSION);
blob.open(oracle.sql.BLOB.MODE_READWRITE);
		OutputStream out = blob.getBinaryOutputStream();
		byte[] buffer = new byte[4096];
		
		ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();
		int bytesRead = 0;
		while ((bytesRead = inputStream.read(buffer))!= -1)
			arrayOutputStream.write(buffer,0,bytesRead);
		arrayOutputStream.close();
		
		byte[] arquivo = arrayOutputStream.toByteArray();

		out.write(arquivo);
		out.flush();
		out.close();
		
		blob.close();
	} catch (SQLException s){
		throw new Throwable(s.getMessage());
	} catch (IOException e){
		throw new Throwable(e.getMessage());
	}
	return blob;
}
Criado 13 de outubro de 2004
Ultima resposta 22 de jan. de 2008
Respostas 7
Participantes 5