Java @GeneratedValue 和 @GenericGenerator 的区别

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18205574/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 23:18:20  来源:igfitidea点击:

Difference between @GeneratedValue and @GenericGenerator

javahibernateorm

提问by user1883212

Sometimes I find them together, sometimes alone... other times they seem to do the same.

有时我发现他们在一起,有时单独……有时他们似乎也做同样的事情。

What's the difference?

有什么不同?

Here are three examples. What do they do of different? Why can't I use just @GeneratedValue for all of them?

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

Example 1

示例 1

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

Example 2

示例 2

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

Example 3

示例 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>();

回答by Kevin Bowersox

When using an ORMit is often necessary to generate a primary key value.

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

The @GeneratedValueannotation denotes that a value for a column, which must be annotated with @Idis generated. The elements strategyand generatoron the annotation describe how the generated value is obtained.

@GeneratedValue注释表示一个列中的值,必须以进行注释@Id被生成。注释上的元素strategygenerator描述了如何获得生成的值。

There are four possible values for the strategyelement on the @GeneratedValueannotation: IDENTITY, AUTO, TABLEand SEQUENCE. See more.

有四个可能的值strategy的元素@GeneratedValue注释:IDENTITYAUTOTABLESEQUENCE查看更多

So to answer Part 2of your question, the code snippet is indicating that the value of userIdwill be obtained through a sequence in the database.

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

The generatorelement of the @GeneratedValueannotation denotes the name of the primary key generator. In Part1of your question, the code snippet indicates that a generatornamed incrementwill be used to obtain the primary key value. incrementis then defined in the next annotation @GenericGenerator. @GenericGeneratoris a hibernate annotation used to denote a custom generator, which can be a class or shortcut to a generator supplied by Hibernate. incrementis a shortcut to a Hibernate generator that:

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

generates identifiers of type long, short or int that are unique only when no other process is inserting data into the same table. Do not use in a cluster.

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

In the Third Partof your question, the code uses a hiloHibernate generator that:

在问题的第三部分中,代码使用了一个hiloHibernate 生成器:

uses a hi/lo algorithm to efficiently generate identifiers of type long, short or int, given a table and column (by default hibernate_unique_key and next_hi respectively) as a source of hi values. The hi/lo algorithm generates identifiers that are unique only for a particular database.

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

回答by Mohd Faizan Khan

@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 is used only to get the generated value. The two arguments strategyand generatorare used to define how the value is obtained.
  • @GenericGenerator is used to map a user defined sequence generator with your hibernate session.
  • You can also use @SequenceGenerator which i have commented in my code. This is not a simple sequence generator but a generator which work on HILOalgorithm. Due to which you will find a lot of gaps in your sequence, like your first value will start from 50 because the default allocation size is 50.
  • @GeneratedValue 仅用于获取生成的值。两个参数strategygenerator用于定义如何获取值。
  • @GenericGenerator 用于将用户定义的序列生成器映射到您的休眠会话。
  • 您还可以使用我在代码中注释的 @SequenceGenerator。这不是一个简单的序列生成器,而是一个适用于HILO算法的生成器。因此,您会发现序列中有很多差距,例如您的第一个值将从 50 开始,因为默认分配大小为 50。

So its better to use @GenericGenerator for your own architecture. But if you are bound to use @SequenceGenerator you have to manually edit your sequence to have two more attributes allocationSize=1and initialValue=1. And to work with these attributes you need to add apropert in your hibernate.cfg.xmlfile

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

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

回答by naXa

To extend the @kevin-bowersox's answer.
Relationships between the Hibernate primary key generation strategies and specific generator respectively, as specified in org.hibernate.id.IdentifierGeneratorFactory

扩展@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);
}

In Hibernate 4.3 I've found org.hibernate.id.factory.internal.DefaultIdentifierGeneratorFactoryclass with 3 more strategies:

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

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

The above fifteen strategies, plus native, are sixteen generation strategies supported in Hibernate by default.

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

Example with native:

示例native

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