如何设置JPA注释以在数据库级别生成ID(主键)?

时间:2018-11-13 22:44:37

标签: java postgresql hibernate jpa spring-data-jpa

让我们假设我有一个时间戳类型为ts的主键。该字段是在插入我的PostgreSQL表时自动生成的。我想告诉JPA /休眠不要发送或填充该字段,但是当实体被持久保存时,只需忽略它即可。

...

@Id
@GeneratedValue(strategy = GenerationType.AUTO, generator = "mygenerator")
@TableGenerator(name = "mygenerator", table = "ms.time_series")
@Column(name = "ts", insertable = false, updatable = false, columnDefinition= "TIMESTAMP WITHOUT TIME ZONE")
private Timestamp ts; 
...

我无法使用它。 @Id@Columns(insertable = false, updatable = false)似乎无法一起使用,该设置已被忽略,并且框架试图以任何方式修改或发送该值。

我在Hibernate中使用最新的Spring 5和Spring Data 2.1.2。数据库是PostgreSQL。

有什么主意吗?如何正确设置注释才能使其正常工作?

1 个答案:

答案 0 :(得分:0)

在映射关系对象时,我们可以选择定义如何处理主键:如果我们要将应用程序带到应用程序来定义此单个值(当我们仅声明@Id注释),或者如果我们要将此责任留给持久性提供者(当我们还声明@GeneratedValue注释时)。

在引用术语“持久性提供程序”时,要知道我们正在引用所选的框架,以便应用程序可以与数据库进行通信。例如Hibernate,EclipseLink和OpenJPA。


GenerationType.AUTO

GenerationType.AUTO 是默认的生成类型,让持久性提供程序选择生成策略。

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id", updatable = false, nullable = false)
private Long id;

GenerationType.IDENTITY

从性能的角度来看, GenerationType.IDENTITY 是最容易使用的,但不是最佳的。它依靠自动递增的数据库列,并允许数据库在每次插入操作时生成一个新值。从数据库的角度来看,这是非常有效的,因为对自动增量列进行了高度优化,并且不需要任何其他语句。

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", updatable = false, nullable = false)
private Long id;

GenerationType.SEQUENCE

GenerationType.SEQUENCE 是我首选的生成主键值并使用数据库序列生成唯一值的方法。

它需要附加的select语句才能从数据库序列中获取下一个值。但这对大多数应用程序没有性能影响。而且,如果您的应用程序必须保留大量的新实体,则可以使用一些特定于Hibernate的优化​​来减少语句的数量。

@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
@Column(name = "id", updatable = false, nullable = false)
private Long id;

GenerationType.TABLE

GenerationType.TABLE 如今很少使用。它通过在数据库表中存储和更新其当前值来模拟序列,这需要使用悲观锁,该悲观锁将所有事务按顺序排列。这会减慢您的应用程序的速度,因此,如果您的数据库支持大多数流行的数据库所支持的序列,则您最好使用 GenerationType.SEQUENCE

@Id
@GeneratedValue(strategy = GenerationType.TABLE)
@Column(name = "id", updatable = false, nullable = false)
private Long id;

建议:

@Id
@GeneratedValue(strategy=GenerationType.TABLE)
@Column(name = "ts", columnDefinition = "TIMESTAMP WITHOUT TIME ZONE",
                     insertable = false, updatable = false)
private Timestamp ts; 

参考: