60

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

有什么不同?

这里有三个例子。他们有什么不同?为什么我不能对所有这些都只使用@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>();
4

3 回答 3

84

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

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

注释strategy上的元素有四个可能的值:、和。 查看更多@GeneratedValueIDENTITYAUTOTABLESEQUENCE

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

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

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

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

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

于 2013-08-13T23:11:04.253 回答
17

扩展@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")
于 2017-01-23T08:50:05.640 回答
11
@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>
于 2016-06-05T09:38:03.370 回答