JPA 为对象关系映射提供了了⼀一种基于 POJO 的持久化模型
- 简化数据持久化代码的开发⼯工作
- 为 Java 社区屏蔽不不同持久化 API 的差异
JPA
定义了持久化的标准,而Hibernate
是持久化的实现。Spring Data JPA
就是在Hibernate
的基础上封装实现的。
JPA提供了很多常用的注解,下面就来讲下关于主键的生成策略,主要的注解有:
@Id
@GeneratedValue(strategy, generator)
@SequenceGenerator(name, sequenceName)
JPA的通用策略生成
其生成规则由@GeneratedValue
设定的。
JPA提供四种标准用法,由@GeneratedValue的源代码可以明显看出。
public @interface GeneratedValue {
/**
* (Optional) The primary key generation strategy
* that the persistence provider must use to
* generate the annotated entity primary key.
*/
GenerationType strategy() default AUTO;
/**
* (Optional) The name of the primary key generator
* to use as specified in the {@link SequenceGenerator}
* or {@link TableGenerator} annotation.
* <p> Defaults to the id generator supplied by persistence provider.
*/
String generator() default "";
}
public enum GenerationType {
/**
* Indicates that the persistence provider must assign
* primary keys for the entity using an underlying
* database table to ensure uniqueness.
*/
TABLE,
/**
* Indicates that the persistence provider must assign
* primary keys for the entity using a database sequence.
*/
SEQUENCE,
/**
* Indicates that the persistence provider must assign
* primary keys for the entity using a database identity column.
*/
IDENTITY,
/**
* Indicates that the persistence provider should pick an
* appropriate strategy for the particular database. The
* <code>AUTO</code> generation strategy may expect a database
* resource to exist, or it may attempt to create one. A vendor
* may provide documentation on how to create such resources
* in the event that it does not support schema generation
* or cannot create the schema resource at runtime.
*/
AUTO
}
JPA
提供的四种标准用法为TABLE
,SEQUENCE
,IDENTITY
,AUTO
。
TABLE:使用一个特定的数据库表格来保存主键。
SEQUENCE:根据底层数据库的序列来生成主键,条件是数据库支持序列。(MySQL不支持)
IDENTITY:主键由数据库自动生成(Oracle不支持这种方式)
AUTO:把主键生成策略交给持久化引擎。(如MySQL会自动对应auto increment。)
简单看下SEQUENCE
的使用:
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator="sequence-generator")
@SequenceGenerator(name="sequence-generator")
看下@SequenceGenerator
的定义:
public @interface SequenceGenerator {
/**
* (Required) A unique generator name that can be referenced
* by one or more classes to be the generator for primary key
* values.
*/
String name();
/**
* (Optional) The name of the database sequence object from
* which to obtain primary key values.
* <p> Defaults to a provider-chosen value.
*/
String sequenceName() default "";
/** (Optional) The catalog of the sequence generator.
*
* @since Java Persistence 2.0
*/
String catalog() default "";
/** (Optional) The schema of the sequence generator.
*
* @since Java Persistence 2.0
*/
String schema() default "";
/**
* (Optional) The value from which the sequence object
* is to start generating.
*/
int initialValue() default 1;
/**
* (Optional) The amount to increment by when allocating
* sequence numbers from the sequence.
*/
int allocationSize() default 50;
}
在我们的应用中,一般选用@GeneratedValue(strategy=GenerationType.AUTO)
这种方式,自动选择主键生成策略,以适应不同的数据库移植。
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
如果使用Hibernate
对JPA
的实现,可以使用Hibernate对主键生成策略的扩展,通过Hibernate
的@GenericGenerator
实现。
Hibernate主键策略生成器
Hbernate提供了多种生成器供选择,基于Annotation的方式通过@GenericGenerator实现.
Hibernate
每种主键生成策略提供接口org.hibernate.id.IdentifierGenerator
的实现类,如果要实现自定义的主键生成策略也必须实现此接口。
public interface IdentifierGenerator {
/**
* The configuration parameter holding the entity name
*/
String ENTITY_NAME = "entity_name";
/**
* The configuration parameter holding the JPA entity name
*/
String JPA_ENTITY_NAME = "jpa_entity_name";
/**
* Used as a key to pass the name used as {@link GeneratedValue#generator()} to the
* {@link IdentifierGenerator} as it is configured.
*/
String GENERATOR_NAME = "GENERATOR_NAME";
/**
* Generate a new identifier.
*
* @param session The session from which the request originates
* @param object the entity or collection (idbag) for which the id is being generated
*
* @return a new identifier
*
* @throws HibernateException Indicates trouble generating the identifier
*/
Serializable generate(SharedSessionContractImplementor session, Object object) throws HibernateException;
}
如何使用呢?
@Id
@GeneratedValue(generator = "hibernate-uuid")
@GenericGenerator(name = "hibernate-uuid", strategy = "uuid")
其中@GenericGenerator
源码如下:
public @interface GenericGenerator {
/**
* unique generator name.
*/
String name();
/**
* Generator strategy either a predefined Hibernate strategy or a fully qualified class name.
*/
String strategy();
/**
* Optional generator parameters.
*/
Parameter[] parameters() default {};
}
- name属性指定生成器名称。
- strategy属性指定具体生成器的类名。
- parameters得到strategy指定的具体生成器所用到的参数。
Hibernate
定义了很多实现好的生成器,在org.hibernate.id.factory.IdentifierGeneratorFactory
的默认实现类中DefaultIdentifierGeneratorFactory
。
public DefaultIdentifierGeneratorFactory() {
register( "uuid2", UUIDGenerator.class );
register( "guid", GUIDGenerator.class ); // can be done with UUIDGenerator + strategy
register( "uuid", UUIDHexGenerator.class ); // "deprecated" for new use
register( "uuid.hex", UUIDHexGenerator.class ); // uuid.hex is deprecated
register( "assigned", Assigned.class );
register( "identity", IdentityGenerator.class );
register( "select", SelectGenerator.class );
register( "sequence", SequenceStyleGenerator.class );
register( "seqhilo", SequenceHiLoGenerator.class );
register( "increment", IncrementGenerator.class );
register( "foreign", ForeignGenerator.class );
register( "sequence-identity", SequenceIdentityGenerator.class );
register( "enhanced-sequence", SequenceStyleGenerator.class );
register( "enhanced-table", TableGenerator.class );
}
关于Hibernate
的主键生成策略如何选择,可以参考文章下面的引用。
参考:
「真诚赞赏,手留余香」
请我喝杯咖啡?
使用微信扫描二维码完成支付
