@GeneratedValue和@GenericGenerator之间的区别

时间:2013-08-13 09:37:17

标签: java hibernate orm

有时候我会一起找到它们,有时候只是一个人......有时候它们似乎也是这样。

有什么区别?

以下是三个例子。他们有什么不同的做法?为什么我不能只为所有这些使用@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>();

3 个答案:

答案 0 :(得分:73)

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

@GeneratedValue注释表示生成了必须使用@Id注释的列的值。注释中的元素strategygenerator描述了如何获取生成的值。

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

因此,要回答问题的第2部分,代码段会指示将通过数据库中的序列获取userId的值。

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

  

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

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

  

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

答案 1 :(得分:8)

延长@ 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") 

答案 2 :(得分: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仅用于获取生成的值。两个参数策略生成器用于定义如何获取值。
  • @GeGeneGenerator用于将用户定义的序列生成器映射到hibernate会话。
  • 你也可以使用我在我的代码中评论过的@SequenceGenerator。这不是一个简单的序列生成器,而是一个处理 HILO 算法的生成器。因此,您会发现序列中存在大量空白,例如您的第一个值将从50开始,因为默认分配大小为50。

因此,最好将@GenericGenerator用于您自己的架构。但是,如果您必须使用@SequenceGenerator,则必须手动编辑序列,以便再增加两个属性 allocationSize = 1 initialValue = 1 。要使用这些属性,您需要在hibernate.cfg.xml文件中添加apropert

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