some more tips

This commit is contained in:
Gavin 2023-05-17 17:08:22 +02:00
parent a8fe62ebb3
commit 491c02f935
2 changed files with 30 additions and 11 deletions

View File

@ -89,13 +89,18 @@ 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")
@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 { ... }
----
[TIP]
====
If the custom SQL should be executed via a `CallableStatement`, just specify `callable=true`.
====
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:
@ -103,9 +108,17 @@ 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`.
Sometimes a custom `insert` or `update` statement assigns a value to a mapped column which is calculated when the statement is executed on the database.
For example, the value might be obtained by calling a SQL function:
[source,java]
----
@SQLInsert(sql = "insert into person (name, id) values (?, gen_random_uuid())")
----
But the entity instance which represents the row being inserted or updated won't be automatically populated with that value.
And so our persistence context loses synchronization with the database.
In situations like this, we may use the `@Generated` annotation to tell Hibernate to reread the state of the entity after each `insert` or `update`.
[[database-generated-columns]]
=== Handling database-generated columns

View File

@ -352,8 +352,8 @@ The `@Column` annotation is not only useful for specifying the column name.
| `scale` | The scale of a `DECIMAL` or `NUMERIC` column type, the digits of precision that occur to the right of the decimal point
| `unique` | Whether the column has a `UNIQUE` constraint
| `nullable` | Whether the column has a `NOT NULL` constraint
| `insertable` | Whether the column should appear in generated SQL `INSERT` and `UPDATE` statements
| `updatable` | Whether the column should appear in generated SQL `INSERT` and `UPDATE` statements
| `insertable` | Whether the column should appear in generated SQL `INSERT` statements
| `updatable` | Whether the column should appear in generated SQL `UPDATE` statements
| `columnDefinition` 💀| A DDL fragment that should be used to declare the column
|===
@ -404,8 +404,8 @@ The `@JoinColumn` annotation is used to customize a foreign key column.
| `referencedColumnName` | The name of the column to which the mapped foreign key column refers
| `unique` | Whether the column has a `UNIQUE` constraint
| `nullable` | Whether the column has a `NOT NULL` constraint
| `insertable` | Whether the column should appear in generated SQL `INSERT` and `UPDATE` statements
| `updatable` | Whether the column should appear in generated SQL `INSERT` and `UPDATE` statements
| `insertable` | Whether the column should appear in generated SQL `INSERT` statements
| `updatable` | Whether the column should appear in generated SQL `UPDATE` statements
| `columnDefinition` 💀| A DDL fragment that should be used to declare the column
| `foreignKey` | A `@ForeignKey` annotation specifying the name of the `FOREIGN KEY` constraint
|===
@ -617,6 +617,12 @@ Unfortunately, the driver for PostgreSQL doesn't allow `BYTEA` or `TEXT` columns
This limitation of the Postgres driver has resulted in a whole cottage industry of bloggers and stackoverflow question-answerers recommending convoluted ways to hack the Hibernate `Dialect` for Postgres to allow an attribute annotated `@Lob` to be written using `setString()` and read using `getString()`.
But simply removing the `@Lob` annotation has exactly the same effect.
Conclusion:
- on PostgreSQL, `@Lob` always means the `OID` type,
- `@Lob` should never be used to map columns of type `BYTEA` or `TEXT`, and
- please don't believe everything you read on stackoverflow.
====
Finally, as an alternative, Hibernate lets you declare an attribute of type `java.sql.Blob` or `java.sql.Clob`.