论坛首页 Java企业应用论坛

谈谈在spring(hibernate)中如何处理oracle大字段

浏览 26095 次
该帖已经被评为精华帖
作者 正文
   发表时间:2005-10-11  
===============================================
在spring中如何处理oracle大字段

  在spring中采用OracleLobHandler来处理oracle大字段(包括clob和blob),则在程序中不需要引用oracle的特殊类,从而能够保证支持我们的代码支持多数据库。

1、首先数据表中的clob类型对应java持久化类的String类型;而blob类型对应byte[]类型
2、定义hibernate标签时,持久化类中对应clob类型的属性的hibernate type应为org.springframework.orm.hibernate.support.ClobStringType;而对应blob类型的属性的hibernate type应为org.springframework.orm.hibernate.support.BlobByteArrayType。
3、以后访问这些对应clob和blob类型的属性时,按普通属性处理,不需要特别编码。
===============================================
请问大家有没有试上面方法在spring中处理Oracle的blob?有这方面经验的朋友说一下怎么实现! 我现在用hibernate操作oracle的blog存取基本是按传统的jdbc方式处理的,如下例子所示。如果用spring提供的org.springframework.jdbc.support.lob.OracleLobHandler类,应该怎么修改! 如果大家有自已更好的方法,请不吝赐教! 3q

例: Customer.hbm.xml
 <?xml version="1.0"?>

<hibernate-mapping package="com.jandar.bo">
     <class name="Customer" table="CUSTOMER">
	<id
	        column="ID"
	        name="Id"
	        type="integer"
	 >
	<generator class="vm" />
	</id>
	<property
		column="NAME"
		length="25"
		name="Name"
		not-null="false"
		type="string"
	/>
	<property
		column="IMAGES"
		name="Images"
		not-null="false"
		type="blob"
	/>
</class>
</hibernate-mapping>


===============================================

[color=blue]
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.SQLException;
import java.util.List;
import net.sf.hibernate.Hibernate;
import net.sf.hibernate.LockMode;
import org.springframework.orm.hibernate.support.HibernateDaoSupport;
import weblogic.jdbc.vendor.oracle.OracleThinBlob;
import com.jandar.bean.ImageBean;
import com.jandar.bo.Customer;
import com.jandar.services.dao.ImageDAO;

public class ImageDAOImpl extends HibernateDaoSupport   
                                           implements ImageDAO{

          byte[] buffer = new byte[10];
	
          public Customer findImage(Customer customer); {
          String getId = "select max(cu.id); from Customer as cu";
          List list = (List);getHibernateTemplate();.find(getId);;
     Customer customerBean =
                    (Customer);getHibernateTemplate();.load 
                    (Customer.class,Integer.valueOf(list.get(0);.toString();););;
	    return customerBean; 
      }

       public void saveImages(Object object);{
              Customer customer = new Customer();;
              ImageBean imageBean = (ImageBean);object;
              OutputStream out = null;
              InputStream fin = null;
              try{
                        //Session session = getSession();;
	       //session.connection();.prepareStatement("insert into ");;
                      //Connection connection = null;
	     //connection = (Connection);session.connection();;
	     //PreparedStatement ps = connection.createStatement();;
	        customer.setName("jack");;
	        customer.setImages(Hibernate.createBlob(buffer););;
   	        getHibernateTemplate();.save(customer);;
	        getHibernateTemplate();.flush();;	
getHibernateTemplate();.refresh(customer, LockMode.UPGRADE);; 
                //since: weblogic8.2 lib 
	        OracleThinBlob blob = (OracleThinBlob);customer.getImages();;
	        out = blob.getBinaryOutputStream();;
	        String fileName = imageBean.getImageName();; 
	        File f = new File(fileName);; 
	        fin = new FileInputStream(f);; 
	        //int count = -1, total = 0; 
	       //fin.read(data);;
	        byte[] data = new byte[ (int); fin.available();]; 
	        int bytesReaded = 0;
              while((bytesReaded=fin.read(data,0,data.length);); != -1); {
	          out.write(data, 0, bytesReaded);;
	}
	         //out.write(data);;
                           customer.setName(imageBean.getName(););;
	           out.flush();;
                           getHibernateTemplate();.flush();;
                }catch(SQLException sqlError);{
                 System.out.println("sql error:  "+ sqlError.getMessage(););;
	}catch(Exception notFound);{
              System.out.println("sql error:  "+ notFound.getMessage(););;
	}finally{
                try{	
	           out.close();;
	            fin.close();;
                }catch(IOException error);{
                	
                }
            }
      }

}
[/color]
   发表时间:2005-10-14  
[color=blue]
<bean id="mySessionFactory2" class="org.springframework.orm.hibernate.LocalSessionFactoryBean">
        <property name="dataSource">
                <ref bean="myDataSource2"/>
         </property>
         <property name="lobHandler">
	<ref bean="oracleLobHandle"/>
         </property>  
</bean>
<bean id="nativeJdbcExtractor" class="org.springframework.jdbc.support.nativejdbc.SimpleNativeJdbcExtractor"/>

<bean id="oracleLobHandle" class="org.springframework.jdbc.support.lob.OracleLobHandler" Lazy-init="true">
 <property name="nativeJdbcExtractor">
    <ref local="nativejdbcExtractor"/>
 </property>
</bean>
[/color]

Spring为处理数据库Lob字段,特别提供了LobHandler接口。在操作Oracle RDBMS过程中,由于Oracle JDBC Driver实现的问题,应用必须采用Oracle原生的数据库连接(比如,oracle.jdbc.OracleConnection)、LOB原生实现(比如,oracle.sql.BLOB、oracle.sql.CLOB)。因此,LobHandler接口存在上述两种实现。简而言之,为操作Oracle数据库,必须使用OracleLobHandler实现。如果操作其他RDBMS类型,则使用DefaultLobHandler。NativeJdbcExtractor是个接口,通过它能够抽象各种连接池。另外Spring还提供两个接口存取Blob,LobCreator及LobHandler

接口LobCreator
[color=blue]
 
     //.....省略某些方法              
     void setBlobAsBytes(PreparedStatement ps, int  paramIndex, byte[] content);throws SQLException;

       void setBlobAsBinaryStream(PreparedStatement ps, int paramIndex,  InputStream contentStream, int contentLength);throws SQLException;
[/color]

接口LobHandler
[color=blue]
 
     //.....省略某些方法              
          byte[] getBlobAsBytes(ResultSet rs, String columnName);throws SQLException;

	byte[] getBlobAsBytes(ResultSet rs, int columnIndex);throws SQLException;

	InputStream getBlobAsBinaryStream(ResultSet rs,String columnName); throws SQLException;

	InputStream getBlobAsBinaryStream(ResultSet rs, int columnIndex); throws SQLException;
[/color]

我现在自定义一个BinaryBlobType类型,请问怎么同时使用LobHandler和Hibernate UserType实现。它们两者的关联怎么配置才算正确呢?是不是UserType和LobHandler两者只能选择一个?

[color=blue]
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 {
        InputStream blobReader = rs.getBinaryStream(names[0]);;
        if (blobReader == null); 
            return null;
        byte[] b = new byte[1024];

        ByteArrayOutputStream os = new ByteArrayOutputStream();;

        try {
            while ((blobReader.read(b);); != -1); 
                os.write(b);;
        } catch (IOException e); {
            throw new SQLException(e.toString(););;
        } finally {
            try {
                os.close();;
            } catch (IOException e); {
            }
        }
        return os.toByteArray();;
    }

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

}
[/color]
0 请登录后投票
   发表时间:2005-10-14  
哪有这么麻烦?不好意思,你贴的实在是太多了,让我失去了看下去的耐心。
spring的sample里面专门有-个操作blob和clob的例子,非常详尽,你看了自然知道如何处理了,我不用在此废话。
0 请登录后投票
   发表时间:2005-10-14  
denis 写道
哪有这么麻烦?不好意思,你贴的实在是太多了,让我失去了看下去的耐心。
spring的sample里面专门有-个操作blob和clob的例子,非常详尽,你看了自然知道如何处理了,我不用在此废话。


spring那个imagedb用的是JdbcDaoSupport里的getJdbcTemplate()实现的!没有用hibernate
0 请登录后投票
   发表时间:2005-10-14  
sigh.....
楼主,我可以告诉你,如果使用hibernate,那么处理这个问题会更简单更透明,你目前最关键的是要学会如何举一反三。

也罢,贴一些片断,明白就明白了,再不明白俺也帮不了你了,我不多做解释。

另:这些配置片断以及代码片段仅在spring1.1.3,hibernate2.1.3上测试通过。理由嘛,这些都是今年初的一个项目中采用的解决方法,而项目结束时使用的spring的版本是1.1.3,hibernate2.13。现在很久没碰spring以及hibernate了,不知道是不是有了更优雅的解决方法?

LocalSessionFactoryBean配置:
引用
<bean id="sessionFactory"
class="org.springframework.orm.hibernate.LocalSessionFactoryBean">
<property name="dataSource">
<ref local="dataSource" />
</property>
<property name="lobHandler">
<ref local="oracleLobHandler" />
</property>

<property name="mappingResources">
<list>...</list>
</property>
<property name="hibernateProperties">...</property>
</bean>


lobHandler:
引用
<bean id="oracleLobHandler"
class="org.springframework.jdbc.support.lob.OracleLobHandler"
lazy-init="true">
<property name="nativeJdbcExtractor">
<ref local="nativeJdbcExtractor" />
</property>

</bean>


nativeJdbcExtractor:
引用
<!--使用dbcp连接池时启用-->
<bean id="nativeJdbcExtractor"
class="org.springframework.jdbc.support.nativejdbc.CommonsDbcpNativeJdbcExtractor"
lazy-init="true" />
<!--使用websphere连接池时启用
<bean id="nativeJdbcExtractor"
class="org.springframework.jdbc.support.nativejdbc.WebSphereNativeJdbcExtractor"
lazy-init="true"/>
-->



pojo blob字段的xdoclet:
 
public Class BinaryFile
private byte[] content;
 /**
   * @hibernate.property
   * column="content"
   * type="org.springframework.orm.hibernate.support.BlobByteArrayType"
   *
   * @return binary array content
   */
  public byte[] getContent();
  {
    return content;
  }



示例代码调用:
File file = some file get from anywhere.........
byte[] fileArray = org.springframework.util.FileCopyUtils.copyToByteArray(file);;
BinaryFile bFile = new BinaryFile();;
bFile.setContent(fileArray);;
getHibernateTemplate();.save(bFile);;
0 请登录后投票
   发表时间:2005-10-17  
denis 写道

pojo blob字段的xdoclet:
 
public Class BinaryFile
private byte[] content;
 /**
   * @hibernate.property
   * column="content"
   * type="org.springframework.orm.hibernate.support.BlobByteArrayType"
   *
   * @return binary array content
   */
  public byte[] getContent();
  {
    return content;
  }



示例代码调用:
File file = some file get from anywhere.........
byte[] fileArray = org.springframework.util.FileCopyUtils.copyToByteArray(file);;
BinaryFile bFile = new BinaryFile();;
bFile.setContent(fileArray);;
getHibernateTemplate();.save(bFile);;


   嗯,多谢denis的指导。在spring1.2和hibernate2.1中也可以通过。看了一下spring和hibernate的源码,无论是自定义的type还是用spring提供的oracleLobHandler最终都要实现org.hibernate.usertype.UserType这个接口。
0 请登录后投票
   发表时间:2005-11-01  
denis 用的数据库是8.1.7?

我想应该是9i以上版本吧?我照着denis贴的内容,jdbc driver用过8.1.7、9.2.0.1、9.2.0.3、9.2.0.4、9.2.0.4、9.2.0.5、10.1.0.2、10.1.0.4、10.2.0.1.0,都没办法往CLOB、BLOB里面弄数据进去。之前google或是javaeye上搜到的资料,无一例外的出错。

似乎对于8i来说,唯一有效的,就是先empty_lob(),然后再for update了。
0 请登录后投票
   发表时间:2005-11-02  
mmwy 写道
denis 用的数据库是8.1.7?

我想应该是9i以上版本吧?我照着denis贴的内容,jdbc driver用过8.1.7、9.2.0.1、9.2.0.3、9.2.0.4、9.2.0.4、9.2.0.5、10.1.0.2、10.1.0.4、10.2.0.1.0,都没办法往CLOB、BLOB里面弄数据进去。之前google或是javaeye上搜到的资料,无一例外的出错。

似乎对于8i来说,唯一有效的,就是先empty_lob(),然后再for update了。


我的版本是9.0.1.0.0用denis的方法是可以,另外我在mysql4.1上也用该方法通过了!是可以直接往数据库插入CLOB、BLOB的,而不用先empty_lob(),然后再for update
0 请登录后投票
   发表时间:2005-11-08  
8I也可以的,我试过
配置差不多的
0 请登录后投票
   发表时间:2005-11-11  
xiang 写道
8I也可以的,我试过
配置差不多的


能否详细介绍一下?我的OS用过RHCE AS2.1、中软3.1,数据库是oracle8.1.7 for linux。
hibernate试过2.1.7,3.0.5。spring用过1.1、1.2.5,都不成功啊。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics