代码之家  ›  专栏  ›  技术社区  ›  paweloque

冬眠和飞锤

  •  7
  • paweloque  · 技术社区  · 16 年前

    有没有办法将Flyweight对象与休眠持久性映射一起使用?我的数据模型包含许多相同的对象。我希望使用Flyweight设计模式并始终引用相同的物理对象,而不是为每个相同的对象创建单独的实例。如何在hibernate中实现这一点?

    4 回复  |  直到 16 年前
        1
  •  3
  •   Max Rydahl Andersen    16 年前

    视情况而定。

    对于实体,Hibernate在默认情况下是正常的,并且希望在事务之间保持一致,因此不会在会话之间共享实体以避免数据的竞争条件——我认为这不是您想要的。

    但为了数据的一致性,我强烈建议您不要这样做——让实体引用实际的不可变flyweight值比尝试对实际实体进行flyweight要好得多。

        2
  •  2
  •   Thomas Jung    16 年前

    是的,您可以使用Hibernate实现Flyweight模式。

    flyweight模式是最大限度地减少内存使用的一种方式 每个实例 除了hibernate对象标识符和一些用于维护对象标识的附加状态之外的所有内容 .

    object identity . 附加状态是实现标识以区分共享公共状态的对象的方法。

    public boolean equals(Object obj){
      Fly other; [..]//check type
      //null checks ommitted
      return other.myState.equals(myState) && other.commonState.equals(commonState); 
    }
    

    如果对象标识在实例之间共享,hibernate会将所有物理实例(引用)解释为同一实例。Hibernate使用equals方法检查对象标识,equal实现必须返回 (! a.equals(a) == true) Equal 必须是反射性的。如果要破坏此契约,则依赖于该契约的所有库都将被破坏(集合、hibernate等)。

    不能使用hibernate对象标识符实现equal方法 区分物体。这将使对象标识依赖于持久性状态(持久或暂时)。

    在hibernate中建模公共状态的一种方法是共享状态对象和flyweight对象之间的一对多关联。(也许有人知道如何在不连接两个表的情况下映射数据?)

    字符串:仅限 internalized strings 将被共享。大多数情况下,这并不是最好的解决方案。它适用于符号(类名、方法名等)。 内部化的字符串永远不会被垃圾收集,您必须有一个字符串实例,它无论如何都会被垃圾收集 new String("..").intern()

        3
  •  1
  •   extraneon    16 年前

    所有JVM是否都优化了字符串的使用,使得当同一个字符串被多次使用时,它始终是同一个物理实例?

    我对此深表怀疑。在同一类文件中,定义如下:

    String s1 = "Yes";
    String s2 = "Yes";
    

    但如果你喜欢:

    String x = loadTextFromFile(); // file contains es
    StringBuilder b = new StringBuilder();
    s2 = b.append("Y").append(x).toString(); // s2 = "Yes"
    

    我认为运行时不会检查并比较所有加载的字符串

    因此,始终将对象与equals()进行比较。无论如何,这是一个很好的建议,因为每一件好事都是从以下几点开始的:

    if (this == o) {
        return true;
    }
    
        4
  •  0
  •   duffymo    16 年前