intro doc for CRUD SQL and @Generated
This commit is contained in:
parent
ccfb51c500
commit
ecaa3f0d62
|
@ -81,9 +81,79 @@ Native SQL queries are _not_ automatically filtered by tenant id; you'll have to
|
|||
[[custom-sql]]
|
||||
=== Using custom-written SQL
|
||||
|
||||
We've already discussed how to run <<native-queries,queries written in SQL>>, but occasionally that's not enough.
|
||||
Sometimes—but much less often than you might expect—we would like to customize the SQL used by Hibernate to perform basic CRUD operations for an entity or collection.
|
||||
|
||||
For this we can use `@SQLInsert` and friends:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@Entity
|
||||
@SQLInsert(sql = "INSERT INTO person (name, id, valid) VALUES (?, ?, true) ", check = COUNT)
|
||||
@SQLUpdate(sql = "UPDATE person SET name = ? where id = ? ")
|
||||
@SQLDelete(sql = "UPDATE person SET valid = false WHERE id = ? ")
|
||||
@SQLSelect(sql = "SELECT id, name FROM person WHERE id = ? and valid = true")
|
||||
public static class Person { ... }
|
||||
----
|
||||
|
||||
Any SQL statement specified by one of these annotations must have exactly the number of JDBC parameters that Hibernate expects, that is, one for each column mapped by the entity, in the exact order Hibernate expects. In particular, the primary key columns must come last.
|
||||
|
||||
However, the `@Column` annotation does lend some flexibility here:
|
||||
|
||||
- if a column should not be written as part of the custom `insert` statement, and has no corresponding JDBC parameter in the custom SQL, map it `@Column(insertable=false)`, or
|
||||
- if a column should not be written as part of the custom `update` statement, and has no corresponding JDBC parameter in the custom SQL, map it `@Column(updatable=false)`.
|
||||
|
||||
In either of these cases, it's possible that the custom `insert` or `update` statement assigns a value to the mapped column as it is written, for example, by calling a SQL function.
|
||||
But our entity instance won't be automatically populated with that value.
|
||||
We may use the `@Generated` annotation to tell Hibernate to reread the state of the entity after each `insert` and/or `update`.
|
||||
|
||||
[[database-generated-columns]]
|
||||
=== Handling database-generated columns
|
||||
|
||||
Sometimes, a column value is assigned or mutated by events that happen in the database, and aren't visible to Hibernate.
|
||||
For example:
|
||||
|
||||
- a table might have a column value populated by a trigger,
|
||||
- a mapped column might have a default value defined in DDL, or
|
||||
- a custom SQL `insert` or `update` statement might assign a value to a mapped column, as we saw in the previous subsection.
|
||||
|
||||
One way to deal with this situation is to explicitly call `refresh()` at appropriate moments, forcing the session to reread the state of the entity.
|
||||
But this is annoying.
|
||||
|
||||
The `@Generated` annotation relieves us of the burden of explicitly calling `refresh()`.
|
||||
It specifies that the value of the annotated entity attribute is generated by the database, and that the generated value should be automatically retrieved using a SQL `returning` clause, or separate `select` after it is generated.
|
||||
|
||||
A useful example is the following mapping:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@Entity
|
||||
class Entity {
|
||||
@Generated @Id
|
||||
@ColumnDefault("gen_random_uuid()")
|
||||
UUID id;
|
||||
}
|
||||
----
|
||||
|
||||
The generated DDL is:
|
||||
|
||||
[source,sql]
|
||||
----
|
||||
create table Entity (
|
||||
id uuid default gen_random_uuid() not null,
|
||||
primary key (uuid)
|
||||
)
|
||||
----
|
||||
|
||||
So here the value of `id` is defined by the column default clause, by calling the PostgreSQL function `gen_random_uuid()`.
|
||||
|
||||
When a column value is generated during updates, use `@Generated(event=UPDATE)`.
|
||||
When a value is generated by both inserts _and_ updates, use `@Generated(event={INSERT,UPDATE})`.
|
||||
|
||||
[TIP]
|
||||
====
|
||||
For columns which should be generated using a SQL `generated always as` clause, prefer the `@GeneratedColumn` annotation, so that Hibernate automatically generates the correct DDL.
|
||||
====
|
||||
|
||||
[[naming-strategies]]
|
||||
=== Naming strategies
|
||||
|
|
Loading…
Reference in New Issue