How to set up JPA annotations to generate ID (Prim

2019-08-04 07:40发布

Let's suppose I have a primary key ts of type Timestamp. That field is generated automatically on insert into my PostgreSQL table. I want to tell JPA/Hibernate not to send or populate that field but just ignore it when the entity is being persisted.

...

@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; 
...

I cannot get it to work. It looks like the @Id and @Columns(insertable = false, updatable = false) don't work together, that setting is being ignored and the framework is trying to modify or send the value in anyways.

I am using the latest Spring 5 and Spring Data 2.1.2 with Hibernate. Database is PostgreSQL.

Any idea what can be wrong? How can I set up the annotations properly for this to work?

1条回答
乱世女痞
2楼-- · 2019-08-04 08:12

At the moment of mapping the relational object, we have the option to define how we are going to treat the primary keys: if we are going to bring the application to the application to define this single value (when we declare only the @Id annotation ), or if we are going to leave this responsibility with the persistence provider (when we also declare the @GeneratedValue annotation ).

When citing the term persistence provider, know that we are referencing the chosen framework so that the application can communicate with the database. Some examples are Hibernate, EclipseLink and OpenJPA.


GenerationType.AUTO

The GenerationType.AUTO is the default generation type and lets the persistence provider choose the generation strategy.

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

GenerationType.IDENTITY

The GenerationType.IDENTITY is the easiest to use but not the best one from a performance point of view. It relies on an auto-incremented database column and lets the database generate a new value with each insert operation. From a database point of view, this is very efficient because the auto-increment columns are highly optimized, and it doesn’t require any additional statements.

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

GenerationType.SEQUENCE

The GenerationType.SEQUENCE is my preferred way to generate primary key values and uses a database sequence to generate unique values.

It requires additional select statements to get the next value from a database sequence. But this has no performance impact for most applications. And if your application has to persist a huge number of new entities, you can use some Hibernate specific optimizations to reduce the number of statements.

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

GenerationType.TABLE

The GenerationType.TABLE gets only rarely used nowadays. It simulates a sequence by storing and updating its current value in a database table which requires the use of pessimistic locks which put all transactions into a sequential order. This slows down your application, and you should, therefore, prefer the GenerationType.SEQUENCE, if your database supports sequences, which most popular databases do.

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

Recommendation:

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

Reference:

查看更多
登录 后发表回答