diff --git a/hibernate-core/src/main/java/org/hibernate/annotations/SQLSelect.java b/hibernate-core/src/main/java/org/hibernate/annotations/SQLSelect.java index 6ed1d13b41f6..6bff0311f35f 100644 --- a/hibernate-core/src/main/java/org/hibernate/annotations/SQLSelect.java +++ b/hibernate-core/src/main/java/org/hibernate/annotations/SQLSelect.java @@ -34,6 +34,22 @@ *
+ * If the {@linkplain #querySpaces tables which affect the query results} + * are specified, then changes to those tables will be flushed before + * execution of the query. + *
+ * For example: + *
+ * @SQLSelect(sql = """
+ * SELECT id, created, text
+ * FROM records
+ * WHERE id = ? and deleted is null
+ * """
+ * querySpaces = "records")
+ * @Entity
+ * public class Record { ... }
+ *
+ * * Optionally, an explicit {@linkplain #resultSetMapping result set mapping} * may be specified. It should have: *
- * This is an alternative to defining a database view and mapping the entity to - * the view using the {@link jakarta.persistence.Table @Table} annotation. + * For example: + *
+ * @Immutable @Entity
+ * @Subselect("""
+ * select type, sum(amount) as total, avg(amount) as average
+ * from details
+ * group by type
+ * """)
+ * @Synchronize("details")
+ * public class Summary {
+ * @Id String type;
+ * Double total;
+ * Double average;
+ * }
+ *
+ * + * This is an alternative to defining a {@linkplain View view} and mapping + * the entity to the view using the {@link jakarta.persistence.Table @Table} + * annotation. + *
+ * It's possible to have an entity class which maps a table, and another + * entity which is defined by a {@code @Subselect} involving the same table. + * In this case, a stateful session is vulnerable to data aliasing effects, + * and it's the responsibility of client code to ensure that changes to the + * first entity are flushed to the database before reading the same data via + * the second entity. The {@link Synchronize @Synchronize} annotation can + * help alleviate this problem, but it's an incomplete solution. We therefore + * recommend the use of {@linkplain org.hibernate.StatelessSession stateless + * sessions} in this situation. * * @see Synchronize + * @see View * * @author Sharath Reddy */ @@ -24,7 +53,7 @@ @Retention(RUNTIME) public @interface Subselect { /** - * The query. + * The subquery, written in native SQL. */ String value(); } diff --git a/hibernate-core/src/main/java/org/hibernate/annotations/Synchronize.java b/hibernate-core/src/main/java/org/hibernate/annotations/Synchronize.java index bfbf114687ff..d543bf02c715 100644 --- a/hibernate-core/src/main/java/org/hibernate/annotations/Synchronize.java +++ b/hibernate-core/src/main/java/org/hibernate/annotations/Synchronize.java @@ -25,7 +25,7 @@ * Ordinarily, Hibernate knows the tables containing the state of an * entity or collection. This annotation might be necessary if: *
* @Immutable @Entity
* @Table(name="summary")
- * @View(query="select type, sum(amount) as total, avg(amount) as average from details group by type")
+ * @View(query="""
+ * select type, sum(amount) as total, avg(amount) as average
+ * from details
+ * group by type
+ * """)
* @Synchronize("details")
* public class Summary {
* @Id String type;
@@ -34,11 +38,12 @@
* Double average;
* }
*
- * * results in the following generated DDL: *
* create view summary - * as select type, sum(amount) as total, avg(amount) as average from details group by type + * as select type, sum(amount) as total, avg(amount) as average + * from details + * group by type **
* If a view is not updatable, we recommend annotating the @@ -47,7 +52,7 @@ * It's possible to have an entity class which maps a table, * and another entity which maps a view defined as a query * against that table. In this case, a stateful session is - * vulnerable to data aliasing effects, and it is the + * vulnerable to data aliasing effects, and it's the * responsibility of client code to ensure that changes to * the first entity are flushed to the database before * reading the same data via the second entity. The @@ -61,6 +66,8 @@ * @since 6.3 * * @author Gavin King + * + * @see Synchronize */ @Incubating @Target(TYPE)