views:

173

answers:

3

I have a Java program that uses Hibernate and MySQL to store a lot of tracing data about the use of the Eclipse IDE. This data contains a lot of strings such as method names, directories, perspective name, etc.

For example, an event object (which is then reflected in a record) can specify the source file and the current method, the user name, etc. Obviously, string data can repeat itself.

As long as it's in memory, much of it is internalized so all repeated string instances point to the same object (I make sure of that). However, with @Basic (I use annotations), Hibernate maps it into a VARCHAR(255), which means a lot of wasted space.

If I was coding the SQL myself, I could have replaced the VARCHAR with an index to a manually-managed string lookup table and saved the space (at the cost of extra lookups).

Is there some way to get Hibernate to do this for me? I'm willing to pay the performance hit for the space.

A: 

I suspect you'll need a string holder object and then make sure all these objects refer to that.

class StringHolder {
  private Long id;
  private String string;

  public StringHolder() {/* Not sure if this is necessary */}

  public StringHolder(String string) {
    this.string = string;
  }

  public void getString() {
    return this.string;
  }
}
sblundy
I thought about that, but was sort of hoping that there was a more elegant way without having to change the way I access the java model on the program side before persisting it....Also, would Hibernate be smart enough to use this is as a lookup? I can't make the string field the ID field...
Uri
No. Hibernate keeps track of things by ID and, normally, strings can't be IDed that way. Most people just don't need to care about space as much as you.
sblundy
Also, the refering table needs a key to refer to and the memory address isn't available, so you'd need to give it an ID anyway
sblundy
+1  A: 

Building on sblundy's answer, you could probably get away with something like:

class Foo {
    // client code uses this to get the value... ignored by Hibernate
    @Transient
    public String getString() {
        return getStringHolder().getString();
    }

    public StringHolder getStringHolder() {...}
}

At least then the client code wouldn't necessarily have to be aware of the change. I don't know if it'd be worth the trouble, though.

CapnNefarious
A: 

I believe you want to look at custom value types. This should allow you to store your strings as integer ID in the database. Of course, you will have to provide the mapping/lookup yourself.

Thilo