论坛首页 Java企业应用论坛

Hibernate:使用用户定义的类型转换CLOB到String(setCharacte...

浏览 8428 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2005-12-06  
终于可以发贴了,在http://www.matrix.org.cn/thread.shtml?topicId=32938&forumId=23上给出问题,竞没人回话,先说问题吧!
我在自己定义的用户类型中遇到下面的问题:
下面这个函数读出数据没有问题:
  public Object nullSafeGet(ResultSet resultSet, String[] stringArray,
                            Object object) throws HibernateException,
      SQLException {
    Reader reader = resultSet.getCharacterStream(stringArray[0]);
    if (reader == null)        return null;

    StringBuffer sb = new StringBuffer();
    try {
            char[] charbuf = new char[4096];
            //解决4096字节大小的限制
            for (int i = reader.read(charbuf); i >0; i= reader.read(charbuf))        {
                    sb.append(charbuf, 0, i);
            }
    }
    catch (IOException e) {
            throw new SQLException( e.getMessage() );
    }
    return sb.toString();
  }
//下面的函数写入数据总是不正确 
  public void nullSafeSet(PreparedStatement preparedStatement, Object object,
                          int _int) throws HibernateException, SQLException {
    try{
      if (object != null) {
//          StringReader r = new StringReader( (String) object);
//下面的方法写入太多的数据会使CLOB为空,几百个字节没有问题
/*          preparedStatement.setCharacterStream(_int, r,
                                               ( (String) object).length());*/

          preparedStatement.setCharacterStream(_int,
              new InputStreamReader(new ByteArrayInputStream(((String) object).getBytes())),
                                               ( (String) object).length());
          System.out.println( (String) object+((String) object).length());
          //下面的方法写入数据的长度有限制
//          preparedStatement.setString(_int,(String) object);         
      } else {
          preparedStatement.setNull(_int, sqlTypes()[0]);
//          preparedStatement.setClob(1,Hibernate.createClob(" "));
      }

    }catch(Exception e){
      e.printStackTrace();
    }
我使用的是JB2005(编译器),Oracle 9.2.0.1.0(企业版),Hibernate 3.0,JDBC thin驱动
我也看过很多有关的贴(读取CLOB相关的),JAVA视线论坛,Hibernate官方站点的
(http://www.hibernate.org/76.html,http://www.hibernate.org/56.html)
Oracle官方站点等等.都没有找到合适的解决方案(或许我的悟性太差了)

还有如果使用OCI驱动连接老是有问题:
thin:        jdbc:oracle:thin:@192.168.0.18:1521:plan 正确
OCI: jdbc:oracle:oci9:@192.168.0.18:1521:plan  找不到URL这个的错误
提示:我的机子其实装了oracle,由于内存太小(256M),所以数据库没有在本机上.
这还需要装oracle客户端吗?

另外我的配置有的也按照网上朋友所说的做了:
<property name="hibernate.jdbc.batch_size">0</property>
<property name="hibernate.jdbc.use_streams_for_binary">true</property>

<property name="dialect">
org.hibernate.dialect.Oracle9Dialect
</property>


请各位指点迷津,注意这里我只想使用自定义的用户类型方式实现CLOB到String的转换!

请看了此贴的朋友,如果可以解决说说解决办法,或是思想,不能解决的能给我一点建议!

初学JAVA时间不长,学HIBERNATE的时间就更短了,难免犯些低级的错误,请不要笑话!
   发表时间:2005-12-06  
第一种:
//          StringReader r = new StringReader( (String) object);
//下面的方法写入太多的数据会使CLOB为空,几百个字节没有问题
/*          preparedStatement.setCharacterStream(_int, r,
                                               ( (String) object).length());*/

          preparedStatement.setCharacterStream(_int,
              new InputStreamReader(new ByteArrayInputStream(((String) object).getBytes())),
                                               ( (String) object).length());

第二种:
//下面的方法写入数据的长度有限制
//          preparedStatement.setString(_int,(String) object);         
第三种:
会抛出无法从套接子读取太多数据的异常
我看了一些帖子说先要清楚,可在这里如何才能获得要清空的那个CLOB呢?
而下面的代码只是创建一个临时CLOB,然后对其写入数据,然后setClob().
      DatabaseMetaData dbMetaData = ps.getConnection().getMetaData();
      log.debug(dbMetaData.getDriverName());
      log.debug(dbMetaData.getDriverMajorVersion() + " " + dbMetaData.getDriverMinorVersion());
      log.debug(dbMetaData.getConnection().getClass().getName());

      if (value == null) {
          ps.setNull(index, sqlTypes()[0]);
      } else if (ORACLE_DRIVER_NAME.equals(dbMetaData.getDriverName())) {
          if ((dbMetaData.getDriverMajorVersion() >= ORACLE_DRIVER_MAJOR_VERSION) &&
                  (dbMetaData.getDriverMinorVersion() >= ORACLE_DRIVER_MINOR_VERSION)) {
              try {
                  // Code compliments of Scott Miller
                  // support oracle clobs without requiring oracle libraries
                  // at compile time
                  // Note this assumes that if you are using the Oracle Driver.
                  // then you have access to the oracle.sql.CLOB class
                  // First get the oracle clob class
                  Class oracleClobClass = Class.forName("oracle.sql.CLOB");

                  // Get the oracle connection class for checking
                  Class oracleConnectionClass = Class.forName("oracle.jdbc.OracleConnection");

                  // now get the static factory method
                  Class[] partypes = new Class[3];
                  partypes[0] = Connection.class;
                  partypes[1] = Boolean.TYPE;
                  partypes[2] = Integer.TYPE;
                  Method createTemporaryMethod = oracleClobClass.getDeclaredMethod("createTemporary", partypes);

                  // now get ready to call the factory method
                  Field durationSessionField = oracleClobClass.getField("DURATION_SESSION");
                  Object[] arglist = new Object[3];

                  //changed from: Connection conn = ps.getConnection();
                  Connection conn = dbMetaData.getConnection();

                  // Make sure connection object is right type
                  if (!oracleConnectionClass.isAssignableFrom(conn.getClass())) {
                      throw new HibernateException("JDBC connection object must be a oracle.jdbc.OracleConnection. " +
                          "Connection class is " + conn.getClass().getName());
                  }

                  arglist[0] = conn;
                  arglist[1] = Boolean.TRUE;
                  arglist[2] = durationSessionField.get(null); //null is valid because of static field

                  // Create our CLOB
                  Object tempClob = createTemporaryMethod.invoke(null, arglist); //null is valid because of static method

                  // get the open method
                  partypes = new Class[1];
                  partypes[0] = Integer.TYPE;

                  Method openMethod = oracleClobClass.getDeclaredMethod("open", partypes);

                  // prepare to call the method
                  Field modeReadWriteField = oracleClobClass.getField("MODE_READWRITE");
                  arglist = new Object[1];
                  arglist[0] = modeReadWriteField.get(null); //null is valid because of static field

                  // call open(CLOB.MODE_READWRITE);
                  openMethod.invoke(tempClob, arglist);
                  // get the getCharacterOutputStream method
                  Method getCharacterOutputStreamMethod = oracleClobClass.getDeclaredMethod("getCharacterOutputStream",
                          null);

                  // call the getCharacterOutpitStream method
                  Writer tempClobWriter = (Writer) getCharacterOutputStreamMethod.invoke(tempClob, null);

                  // write the string to the clob
                  tempClobWriter.write((String) value);
                  tempClobWriter.flush();
                  tempClobWriter.close();

                  // get the close method
                  Method closeMethod = oracleClobClass.getDeclaredMethod("close", null);

                  // call the close method
                  closeMethod.invoke(tempClob, null);

                  // add the clob to the statement
                  ps.setClob(index, (Clob) tempClob);

                  LobCleanUpInterceptor.registerTempLobs(tempClob);
              } catch (ClassNotFoundException e) {
                  // could not find the class with reflection
                  throw new HibernateException("Unable to find a required class.\n" + e.getMessage());
              } catch (NoSuchMethodException e) {
                  // could not find the metho with reflection
                  throw new HibernateException("Unable to find a required method.\n" + e.getMessage());
              } catch (NoSuchFieldException e) {
                  // could not find the field with reflection
                  throw new HibernateException("Unable to find a required field.\n" + e.getMessage());
              } catch (IllegalAccessException e) {
                  throw new HibernateException("Unable to access a required method or field.\n" + e.getMessage());
              } catch (InvocationTargetException e) {
                  throw new HibernateException(e.getMessage());
              } catch (IOException e) {
                  throw new HibernateException(e.getMessage());
              }
          } else {
              throw new HibernateException("No CLOBS support. Use driver version " + ORACLE_DRIVER_MAJOR_VERSION +
                  ", minor " + ORACLE_DRIVER_MINOR_VERSION);
          }
      } else {
          String str = (String) value;
          StringReader r = new StringReader(str);
          ps.setCharacterStream(index, r, str.length());
      }             
注意:LobCleanUpInterceptor我已经实现,并且在openSession()时这样写的openSession(new LobCleanUpInterceptor())
0 请登录后投票
   发表时间:2005-12-07  
:( 怎么没人帮忙啊,难道......?
我也是考虑了很长时间实在是没法了才发贴的,如果问题大家觉得不难,不妨可以为我解开其中的迷惑.

按照Robbin的说法,也得先得到这个CLOB才能为它清空,然后再写入数据,可是在nullSafeSet中不知如何才能做到.给我的感觉是无法办到,因为前一个nullSafeSet如果是获取数据时执行,那么后一个就应该是更新数据时执行.这里看起来像是原子操作.要不然再在更新过程中再执行一次更新把它清空.我想这样是不合理的!
谁有好的想法可以一起讨论一下,虽然我是新的不能再新的新手(对于JAVA来说),就因为这样我希望得到更多高手帮助.
0 请登录后投票
   发表时间:2005-12-14  
Hibernate3我曾经尝试过映射为text,没有4096字节限制。不知道是不是我用Oracle10的JDBC驱动的原因,不过在Oracle9.2运行正常。
好像同一列如果有多个Clob字段,保存时候有bug,后来换spring的ClobStringType映射正常。
楼主可以试试。
0 请登录后投票
   发表时间:2005-12-14  
没怎么看你的问题,不过Oracle Clob在映射到String下,做数据库操作时,跟Oracle JDBC驱动有狠大关系,前几天我还被这个问题搞叻一把。最后到oracle.com下载的Oracle 10g Release 2的最新驱动,换上去,什么毛病都没有。
0 请登录后投票
   发表时间:2005-12-15  
难道非的换驱动吗?
我现在用最原始的办法去保存,取的话仍采用上面的方法没有问题.
但这样做已经没有利用到UserType带来的方便性了.期待有好的解决方案!

还有请问楼两位你们用的是UserType方式实现的吗,还是怎么做的?

我想的是如果使用UserType就可以在以后代码维护上面变的更加简单了.

期待使用UserType方式实现Clob到String的转换

最后感谢楼上两位给予的回复!!!
0 请登录后投票
   发表时间:2005-12-15  
3楼的朋友说spring的ClobStringType可以做到,我的一个新手,平时工作用的是Delphi,只是现在想转向使用JAVA开发,一下子没那么多经历学这么多新的东西,不过听说spring是开源的.不知是否可以通过它的源码找到一些灵感?
我只是这么想!有时间我也学学spring.看看它是如何实现的.




JAVA的第三方产品太多了,学的真是很累很烦,不知何时可以跟的上大家.希望大家能与我共同探讨技术问题,同时也感谢能与我一起探讨问题的朋友与提出各种问题的朋友,从他们的回复与问题中让我学到了很多东西.
0 请登录后投票
论坛首页 Java企业应用版

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