【问题标题】:Difference between @GeneratedValue and @GenericGenerator@GeneratedValue 和 @GenericGenerator 之间的区别
【发布时间】:2013-08-14 20:40:35
【问题描述】:

有时我发现他们在一起,有时单独......其他时候他们似乎也这样做。

有什么区别?

这里有三个例子。他们有什么不同?为什么我不能对所有这些都只使用@GeneratedValue?

示例 1

@Id
@GeneratedValue(generator="increment")
@GenericGenerator(name="increment", strategy = "increment") 
Long id;

示例 2

@Id @GeneratedValue(strategy=GenerationType.SEQUENCE)
private int userId;

示例 3

@ElementCollection
@JoinTable(name="Address",
   joinColumns=@JoinColumn(name="user_id")
)
@GenericGenerator(name="hilo-gen", strategy="hilo")
@CollectionId(columns = @Column(name="Address_id"), generator = "hilo-gen", type = @Type(type="long"))
Collection<Addr> listOfAddresses = new ArrayList<Addr>();

【问题讨论】:

    标签: java hibernate orm


    【解决方案1】:

    使用ORM 时,通常需要生成主键值。

    @GeneratedValue 注解表示生成了一个列的值,必须用@Id 进行注解。注解上的strategygenerator元素描述了如何获取生成的值。

    @GeneratedValue 注释上的 strategy 元素有四个可能的值:IDENTITYAUTOTABLESEQUENCESee more.

    所以回答你问题的第二部分,代码sn-p表示userId的值将通过数据库中的序列获取。

    @GeneratedValue 注释的generator 元素表示主键生成器的名称。在您问题的Part1中,代码 sn-p 表示将使用名为incrementgenerator 来获取主键值。然后在下一个注释@GenericGenerator 中定义increment@GenericGenerator 是一个 hibernate 注释,用于表示自定义生成器,它可以是 Hibernate 提供的生成器的类或快捷方式。 increment 是 Hibernate 生成器的快捷方式:

    生成只有唯一的 long、short 或 int 类型的标识符 当没有其他进程将数据插入同一个表时。不要 在集群中使用。

    在您问题的第三部分中,代码使用了hilo Hibernate 生成器:

    使用 hi/lo 算法有效地生成类型标识符 长,短或整数,给定一个表和列(默认情况下 hibernate_unique_key 和 next_hi 分别)作为 hi 的来源 价值观。 hi/lo 算法生成唯一的标识符 对于特定的数据库。

    【讨论】:

      【解决方案2】:
      @Entity
      @Table(name="Honey")
      public class Honey implements Serializable{
          private static final long serialVersionUID = 42L;
          @Id
          //@SequenceGenerator(name="honeySequence",sequenceName="HONEY_SEQ")
          @org.hibernate.annotations.GenericGenerator(name="honeySequence", strategy = "sequence", 
          parameters = { 
                  @Parameter(name="sequence", value="HONEY_SEQ") } 
          )
          @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="honeySequence")
          private int Id;
          private String name;
          private String taste;
      
      • @GeneratedValue 仅用于获取生成的值。 strategygenerator 这两个参数用于定义如何获取值。
      • @GenericGenerator 用于将用户定义的序列生成器映射到您的休眠会话。
      • 您也可以使用我在代码中注释的@SequenceGenerator。这不是一个简单的序列生成器,而是一个在 HILO 算法上工作的生成器。因此,您会发现序列中有很多空白,例如您的第一个值将从 50 开始,因为默认分配大小为 50。

      所以最好将@GenericGenerator 用于您自己的架构。但是,如果您一定要使用@SequenceGenerator,您必须手动编辑您的序列以拥有另外两个属性allocationSize=1initialValue=1。要使用这些属性,您需要在 hibernate.cfg.xml 文件中添加属性

      <property name="hibernate.id.new_generator_mappings">true</property>
      

      【讨论】:

      • 我知道这是一篇旧帖子。所以在你上面的例子中,序列“HONEY_SEQ”是在实际数据库(Oracle、DB2 等)中为该表创建的序列吗?
      • 是的。 HONEY_SEQ 是在数据库上创建的数据库序列的名称。
      • 嗨@cogitoboy,Hibernate 会自动创建“HONEY_SEQ”还是我需要在数据库中创建它?
      • @jumping_monkey,hibernate无法创建seq,需要手动创建db seq。
      • 谢谢@MohdFaizanKhan,我就是这么想的。在我手动创建它之前它从来没有工作过。不过,这将是一个“不错的”功能。
      【解决方案3】:

      扩展@kevin-bowersox 的答案。
      Hibernate主键生成策略与具体生成器之间的关系,具体见org.hibernate.id.IdentifierGeneratorFactory

      static {
          GENERATORS.put("uuid", UUIDHexGenerator.class);     // "deprecated" for new use
          GENERATORS.put("hilo", TableHiLoGenerator.class);   // removed in Hibernate 5
          GENERATORS.put("assigned", Assigned.class);
          GENERATORS.put("identity", IdentityGenerator.class);
          GENERATORS.put("select", SelectGenerator.class);
          GENERATORS.put("sequence", SequenceGenerator.class);
          GENERATORS.put("seqhilo", SequenceHiLoGenerator.class);
          GENERATORS.put("increment", IncrementGenerator.class);
          GENERATORS.put("foreign", ForeignGenerator.class);
          GENERATORS.put("guid", GUIDGenerator.class);
          GENERATORS.put("uuid.hex", UUIDHexGenerator.class); // uuid.hex is deprecated
          GENERATORS.put("sequence-identity", SequenceIdentityGenerator.class);
      }
      

      在 Hibernate 4.3 中,我发现 org.hibernate.id.factory.internal.DefaultIdentifierGeneratorFactory 类还有 3 个策略:

          register("uuid2", UUIDGenerator.class);
          register("enhanced-sequence", SequenceStyleGenerator.class);
          register("enhanced-table", TableGenerator.class);
      

      以上十五种策略,加上native,是Hibernate默认支持的十六种生成策略。

      native 为例:

      @GeneratedValue(generator = "nativeGenerator")
      @GenericGenerator(name = "nativeGenerator", strategy = "native")
      

      【讨论】:

      • 刚刚偶然发现"native" 的这种用法 - 有没有一种“更安全”的方式来声明这个策略?找不到它的枚举(我不是“神奇”字符串的忠实粉丝)。
      • @Michal 我什么都不知道。总是可以选择自己声明一个常量public static final String NATIVE = "native";
      • 我还看到策略名称在 Hibernate 源代码中是硬编码的。
      猜你喜欢
      • 2023-03-29
      • 1970-01-01
      • 2021-12-25
      • 2020-05-10
      • 2014-09-20
      • 2010-10-28
      • 2015-10-04
      • 2012-08-12
      • 2011-02-18
      相关资源
      最近更新 更多