Skip to content

Commit

Permalink
improve javadoc for @view, @subselect, and @SQLSelect
Browse files Browse the repository at this point in the history
  • Loading branch information
gavinking committed Jan 20, 2025
1 parent d71a2e5 commit cf0f2e4
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,22 @@
* <li>the foreign key, in the case of a collection.
* </ol>
* <p>
* 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.
* <p>
* For example:
* <pre>
* &#64;SQLSelect(sql = """
* SELECT id, created, text
* FROM records
* WHERE id = ? and deleted is null
* """
* querySpaces = "records")
* &#64;Entity
* public class Record { ... }
* </pre>
* <p>
* Optionally, an explicit {@linkplain #resultSetMapping result set mapping}
* may be specified. It should have:
* <ol>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,49 @@
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
* Maps an immutable and read-only entity to a given SQL {@code select} expression.
* Maps an {@linkplain Immutable immutable} and read-only entity to a given
* SQL {@code select} expression.
* <p>
* 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:
* <pre>
* &#64;Immutable &#64;Entity
* &#64;Subselect("""
* select type, sum(amount) as total, avg(amount) as average
* from details
* group by type
* """)
* &#64;Synchronize("details")
* public class Summary {
* &#64;Id String type;
* Double total;
* Double average;
* }
* </pre>
* <p>
* 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.
* <p>
* 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
*/
@Target(TYPE)
@Retention(RUNTIME)
public @interface Subselect {
/**
* The query.
* The subquery, written in native SQL.
*/
String value();
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
* Ordinarily, Hibernate knows the tables containing the state of an
* entity or collection. This annotation might be necessary if:
* <ul>
* <li>an entity or collection maps a database view,
* <li>an entity or collection maps a database {@linkplain View view},
* <li>an entity or collection is persisted using handwritten SQL,
* that is, using {@link SQLSelect @SQLSelect} and friends, or
* <li>an entity is mapped using {@link Subselect @Subselect}.
Expand All @@ -41,6 +41,9 @@
* @author Sharath Reddy
*
* @see org.hibernate.query.SynchronizeableQuery
* @see View
* @see Subselect
* @see SQLSelect
*/
@Target({TYPE, FIELD, METHOD})
@Retention(RUNTIME)
Expand Down
15 changes: 11 additions & 4 deletions hibernate-core/src/main/java/org/hibernate/annotations/View.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,24 @@
* <pre>
* &#64;Immutable &#64;Entity
* &#64;Table(name="summary")
* &#64;View(query="select type, sum(amount) as total, avg(amount) as average from details group by type")
* &#64;View(query="""
* select type, sum(amount) as total, avg(amount) as average
* from details
* group by type
* """)
* &#64;Synchronize("details")
* public class Summary {
* &#64;Id String type;
* Double total;
* Double average;
* }
* </pre>
* <p>
* results in the following generated DDL:
* <pre>
* 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
* </pre>
* <p>
* If a view is not updatable, we recommend annotating the
Expand All @@ -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
Expand All @@ -61,6 +66,8 @@
* @since 6.3
*
* @author Gavin King
*
* @see Synchronize
*/
@Incubating
@Target(TYPE)
Expand Down

0 comments on commit cf0f2e4

Please sign in to comment.