-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 5 posts ] 
Author Message
 Post subject: Oracle's 4000 character VARCHAR2 limit
PostPosted: Mon Sep 15, 2003 4:35 pm 
Beginner
Beginner

Joined: Wed Aug 27, 2003 8:55 am
Posts: 28
Location: Dallas, TX
We use Oracle as our database. It has a limit of 4000 characters for its VARCHAR2 datatype. So, when I wanted to persist some *long* String data, I had to come up with something more than just one VARCHAR2 column.

I originally looked at using a CLOB, but after investigating the effort required to deal with Oracle CLOBs, I decided to pass.

The solution I came up with was to break the String into 4000-character Strings and persist them as a 1-N. Basically the table looks like this:

Code:
PARENT_ID
SEQ
TEXT


Piece of cake. Next I wanted a component that encapsulated this structure, so I came up with LongString:

Code:
public class LongString {
 
 
  private List stringList = Collections.EMPTY_LIST;


  public List getStringList() {
    return stringList;
  }

  public void setStringList(List list) {
    stringList = list;
  }
 
  public String getText() {
   
    if (stringList.size() == 0) {
      return null;
    }
   
    StringBuffer text = new StringBuffer(4000 * stringList.size());
    for (int i = 0; i < stringList.size(); i++) {
      text.append(stringList.get(i));
     
    }
    return text.toString();   
  }
 
  public void setText(String text) {   
   
    if (text == null) {
      stringList = Collections.EMPTY_LIST;
    }
   
    stringList = new ArrayList();
         
    for (int i = 0; i < ((text.length() - 1) / 4000) + 1; i++) {
      int start = i * 4000;
      int end = Math.min(start + 4000, text.length());
      stringList.add(text.substring(start, end));
    }
  }
}


Now any class that wants to have some long text, it uses that LongString as so:

Code:
public class Contest {

  private LongString html = new LongString();

  /**
   * @hibernate.list
   *     table="text"
   *     lazy="true"
   *     cascade="all"
   *
   * @hibernate.collection-key
   *     column="parent_id"
   *
   * @hibernate.collection-index
   *     column="sequence"
   *
   * @hibernate.collection-element
   *     column="text"
   *     type="string"
   */
  private List getHtmlList() {
    return html.getStringList();
  }
 
  private void setHtmlList(List htmlList) {
    html.setStringList(htmlList);
  }

  public String getHtml() {
    return html.getText();
  }

  public void setHtml(String html) {
    this.html.setText(html);
  }

}


The html get/set pair is exposed to the application so the persistance implementation is hidden. The htmlList get/set pair is private and for Hiberante's eyes only.

This leads me to my questions:

    Althought the scruture of the LongString is captured in one class, having to expose the List in enclosing classes via private methods is still yucky. To me, it still let's some of the Hibernate-related stuff leak out into my other classes.

    I don't like the fact the LongString can't make defensive copies of its data. Maybe it can, but when I tried it, Bad Stuff happened.
    Without the defensive copying, you can do stuff like:

Code:
LongString longString = new LongString();
List stringList = new ArrayList();
stringList.add("Some String");
longString.setStringList(stringList);
stringList.clear(); // oh no - we just blew away our LongString!


What are some other solutions to persisting long Strings in Oracle without resorting to CLOBs?

Thanks.

Ryan


Top
 Profile  
 
 Post subject:
PostPosted: Mon Sep 15, 2003 4:51 pm 
Beginner
Beginner

Joined: Thu Sep 04, 2003 2:50 pm
Posts: 45
Location: US: New York NY
let me ask the stupid question, cause I'm curious: why are you re-inventing the wheel? Using a clob is clearly defined here: http://hibernate.bluemars.net/56.html

Trying to store very long strings in memory will eventually lead to an "Out of Memory" exception eventually.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Sep 15, 2003 9:33 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 3:00 pm
Posts: 1816
Location: Austin, TX
You could use a LONG column. But Oracle (at least through 8i) restricts you to one LONG column max per table.

We actually completely eschew the idea of using LOBs of any type in Oracle because of its crappy support for LOBs in its JDBC drivers. We just limit all "long" text to 4000 characters.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Sep 15, 2003 9:51 pm 
Beginner
Beginner

Joined: Wed Aug 27, 2003 8:55 am
Posts: 28
Location: Dallas, TX
steve wrote:
You could use a LONG column. But Oracle (at least through 8i) restricts you to one LONG column max per table.

We actually completely eschew the idea of using LOBs of any type in Oracle because of its crappy support for LOBs in its JDBC drivers. We just limit all "long" text to 4000 characters.


Yes. I would rather not use LOBs either. And I am not trying to reinvent the wheel (CLOBs). In fact, I originally tried to implement this with CLOBs (Oracle 8.1.7) and it proved to be a real PITA.

However, we do not have the option of limiting "long" text. Some objects require Strings longer than 4000 characters. Also, I do like the 1-N solution we have developed because the data is stored in the database in a readable format.

However, I would like to be able to create a component that I can reuse to handle this. Preferrably, just a String with a customized persister. However, I have not seen a way I can customize how an object/property is persisted over an arbitrary number of columns.

Any suggestions?

Ryan


Top
 Profile  
 
 Post subject:
PostPosted: Mon Sep 15, 2003 10:06 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 3:00 pm
Posts: 1816
Location: Austin, TX
Oracle LONG columns are 32,786 (I think... its more than 32 thousand) characters. But sure, its still a limit.

And really you are reinventing the wheel as this is basically what CLOB columns are doing, in terms of storing text in linked sequences.

You might check out the ClassPersister interface. You might be able to utilize that concept to implement what you want. A custom ClassPersister implementation can then be associated to a Hibernate mapped class through the class attribute of the <class> element.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 5 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.