我可以透明地避免Hibernate在数据库中避免字符串重复吗?

时间:2023-02-08 08:40:28

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.

我有一个Java程序,它使用Hibernate和MySQL来存储大量有关Eclipse IDE使用的跟踪数据。此数据包含许多字符串,例如方法名称,目录,透视图名称等。

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.

只要它在内存中,其中大部分是内化的,所以所有重复的字符串实例都指向同一个对象(我确保这一点)。但是,使用@Basic(我使用注释),Hibernate将它映射到VARCHAR(255),这意味着浪费了大量空间。

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).

如果我自己编写SQL,我可以将VARCHAR替换为手动管理的字符串查找表的索引并保存空间(以额外查找为代价)。

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

有没有办法让Hibernate为我做这个?我愿意支付这个空间的性能。

3 个解决方案

#1


1  

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

基于sblundy的回答,你可能会得到类似的东西:

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.

至少那时客户端代码不一定必须知道这种变化。不过,我不知道是否值得这么麻烦。

#2


0  

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

#3


0  

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.

我相信你想看看自定义价值类型。这应该允许您将字符串存储为数据库中的整数ID。当然,您必须自己提供映射/查找。

#1


1  

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

基于sblundy的回答,你可能会得到类似的东西:

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.

至少那时客户端代码不一定必须知道这种变化。不过,我不知道是否值得这么麻烦。

#2


0  

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

#3


0  

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.

我相信你想看看自定义价值类型。这应该允许您将字符串存储为数据库中的整数ID。当然,您必须自己提供映射/查找。