From 5e23b7fd025e4bc8c564a71681efcd3ce0f3889f Mon Sep 17 00:00:00 2001 From: Vlad Mihalcea Date: Mon, 5 Jun 2017 17:27:23 +0300 Subject: [PATCH] HHH-11186 - Add examples for all Hibernate annotations Document @TableGenerator --- .../userguide/appendices/Annotations.adoc | 2 +- .../domain/extras/id/TableGenerator.sql | 4 - .../domain/extras/id/UnnamedTable.java | 9 -- ...ators-table-configured-mapping-example.sql | 5 + ...ators-table-configured-persist-example.sql | 78 ++++++++++++++++ ...nerators-table-unnamed-mapping-example.sql | 5 + .../chapters/domain/identifiers.adoc | 61 ++++++++++--- ...a => SequenceGeneratorConfiguredTest.java} | 2 +- ...t.java => SequenceGeneratorNamedTest.java} | 2 +- ...java => SequenceGeneratorUnnamedTest.java} | 2 +- .../TableGeneratorConfiguredTest.java | 91 +++++++++++++++++++ .../identifier/TableGeneratorUnnamedTest.java | 85 +++++++++++++++++ .../src/test/resources/log4j.properties | 2 + .../id/IdentifierGeneratorHelper.java | 1 + .../hibernate/id/enhanced/TableGenerator.java | 1 + 15 files changed, 319 insertions(+), 31 deletions(-) delete mode 100644 documentation/src/main/asciidoc/userguide/chapters/domain/extras/id/TableGenerator.sql delete mode 100644 documentation/src/main/asciidoc/userguide/chapters/domain/extras/id/UnnamedTable.java create mode 100644 documentation/src/main/asciidoc/userguide/chapters/domain/extras/id/identifiers-generators-table-configured-mapping-example.sql create mode 100644 documentation/src/main/asciidoc/userguide/chapters/domain/extras/id/identifiers-generators-table-configured-persist-example.sql create mode 100644 documentation/src/main/asciidoc/userguide/chapters/domain/extras/id/identifiers-generators-table-unnamed-mapping-example.sql rename documentation/src/test/java/org/hibernate/userguide/mapping/identifier/{ConfiguredSequenceTest.java => SequenceGeneratorConfiguredTest.java} (95%) rename documentation/src/test/java/org/hibernate/userguide/mapping/identifier/{NamedSequenceTest.java => SequenceGeneratorNamedTest.java} (96%) rename documentation/src/test/java/org/hibernate/userguide/mapping/identifier/{UnnamedSequenceTest.java => SequenceGeneratorUnnamedTest.java} (95%) create mode 100644 documentation/src/test/java/org/hibernate/userguide/mapping/identifier/TableGeneratorConfiguredTest.java create mode 100644 documentation/src/test/java/org/hibernate/userguide/mapping/identifier/TableGeneratorUnnamedTest.java diff --git a/documentation/src/main/asciidoc/userguide/appendices/Annotations.adoc b/documentation/src/main/asciidoc/userguide/appendices/Annotations.adoc index d9ede394b3..42ed5ae0d8 100644 --- a/documentation/src/main/asciidoc/userguide/appendices/Annotations.adoc +++ b/documentation/src/main/asciidoc/userguide/appendices/Annotations.adoc @@ -588,7 +588,7 @@ See the <> section for more info. [[annotations-jpa-temporal]] ==== `@Temporal` diff --git a/documentation/src/main/asciidoc/userguide/chapters/domain/extras/id/TableGenerator.sql b/documentation/src/main/asciidoc/userguide/chapters/domain/extras/id/TableGenerator.sql deleted file mode 100644 index d66d067f92..0000000000 --- a/documentation/src/main/asciidoc/userguide/chapters/domain/extras/id/TableGenerator.sql +++ /dev/null @@ -1,4 +0,0 @@ -create table hibernate_sequences( - sequence_name VARCHAR NOT NULL, - next_val INTEGER NOT NULL -) \ No newline at end of file diff --git a/documentation/src/main/asciidoc/userguide/chapters/domain/extras/id/UnnamedTable.java b/documentation/src/main/asciidoc/userguide/chapters/domain/extras/id/UnnamedTable.java deleted file mode 100644 index 521283d526..0000000000 --- a/documentation/src/main/asciidoc/userguide/chapters/domain/extras/id/UnnamedTable.java +++ /dev/null @@ -1,9 +0,0 @@ -@Entity -public class MyEntity { - - @Id - @GeneratedValue( generation = TABLE ) - public Integer id; - - ... -} \ No newline at end of file diff --git a/documentation/src/main/asciidoc/userguide/chapters/domain/extras/id/identifiers-generators-table-configured-mapping-example.sql b/documentation/src/main/asciidoc/userguide/chapters/domain/extras/id/identifiers-generators-table-configured-mapping-example.sql new file mode 100644 index 0000000000..4e7ca0b94c --- /dev/null +++ b/documentation/src/main/asciidoc/userguide/chapters/domain/extras/id/identifiers-generators-table-configured-mapping-example.sql @@ -0,0 +1,5 @@ +create table table_identifier ( + table_name varchar2(255 char) not null, + product_id number(19,0), + primary key (table_name) +) \ No newline at end of file diff --git a/documentation/src/main/asciidoc/userguide/chapters/domain/extras/id/identifiers-generators-table-configured-persist-example.sql b/documentation/src/main/asciidoc/userguide/chapters/domain/extras/id/identifiers-generators-table-configured-persist-example.sql new file mode 100644 index 0000000000..d4ba98a01b --- /dev/null +++ b/documentation/src/main/asciidoc/userguide/chapters/domain/extras/id/identifiers-generators-table-configured-persist-example.sql @@ -0,0 +1,78 @@ +select + tbl.product_id +from + table_identifier tbl +where + tbl.table_name = ? +for update + +-- binding parameter [1] - [Product] + +insert +into + table_identifier + (table_name, product_id) +values + (?, ?) + +-- binding parameter [1] - [Product] +-- binding parameter [2] - [1] + +update + table_identifier +set + product_id= ? +where + product_id= ? + and table_name= ? + +-- binding parameter [1] - [6] +-- binding parameter [2] - [1] + +select + tbl.product_id +from + table_identifier tbl +where + tbl.table_name= ? for update + +update + table_identifier +set + product_id= ? +where + product_id= ? + and table_name= ? + +-- binding parameter [1] - [11] +-- binding parameter [2] - [6] + +insert +into + Product + (product_name, id) +values + (?, ?) + +-- binding parameter [1] as [VARCHAR] - [Product 1] +-- binding parameter [2] as [BIGINT] - [1] + +insert +into + Product + (product_name, id) +values + (?, ?) + +-- binding parameter [1] as [VARCHAR] - [Product 2] +-- binding parameter [2] as [BIGINT] - [2] + +insert +into + Product + (product_name, id) +values + (?, ?) + +-- binding parameter [1] as [VARCHAR] - [Product 3] +-- binding parameter [2] as [BIGINT] - [3] diff --git a/documentation/src/main/asciidoc/userguide/chapters/domain/extras/id/identifiers-generators-table-unnamed-mapping-example.sql b/documentation/src/main/asciidoc/userguide/chapters/domain/extras/id/identifiers-generators-table-unnamed-mapping-example.sql new file mode 100644 index 0000000000..82b3326ad2 --- /dev/null +++ b/documentation/src/main/asciidoc/userguide/chapters/domain/extras/id/identifiers-generators-table-unnamed-mapping-example.sql @@ -0,0 +1,5 @@ +create table hibernate_sequences ( + sequence_name varchar2(255 char) not null, + next_val number(19,0), + primary key (sequence_name) +) \ No newline at end of file diff --git a/documentation/src/main/asciidoc/userguide/chapters/domain/identifiers.adoc b/documentation/src/main/asciidoc/userguide/chapters/domain/identifiers.adoc index 0641856578..e2460c0a7a 100644 --- a/documentation/src/main/asciidoc/userguide/chapters/domain/identifiers.adoc +++ b/documentation/src/main/asciidoc/userguide/chapters/domain/identifiers.adoc @@ -261,7 +261,7 @@ The simplest form is to simply request sequence generation; Hibernate will use a ==== [source,java] ---- -include::{sourcedir}/UnnamedSequenceTest.java[tag=identifiers-generators-sequence-mapping-example, indent=0] +include::{sourcedir}/SequenceGeneratorUnnamedTest.java[tag=identifiers-generators-sequence-mapping-example, indent=0] ---- ==== @@ -272,7 +272,7 @@ Using `javax.persistence.SequenceGenerator`, you can specify a specific database ==== [source,java] ---- -include::{sourcedir}/NamedSequenceTest.java[tag=identifiers-generators-sequence-mapping-example, indent=0] +include::{sourcedir}/SequenceGeneratorNamedTest.java[tag=identifiers-generators-sequence-mapping-example, indent=0] ---- ==== @@ -283,7 +283,7 @@ The `javax.persistence.SequenceGenerator` annotataion allows you to specify addi ==== [source,java] ---- -include::{sourcedir}/ConfiguredSequenceTest.java[tag=identifiers-generators-sequence-mapping-example, indent=0] +include::{sourcedir}/SequenceGeneratorConfiguredTest.java[tag=identifiers-generators-sequence-mapping-example, indent=0] ---- ==== @@ -313,30 +313,63 @@ If the application is not usually creating many new instances of a given type of ==== [[identifiers-generators-table]] -==== Using identifier table +==== Using table identifier generator -Hibernate achieves table-based identifier generation based on its `org.hibernate.id.enhanced.TableGenerator` id generator which defines a table capable of holding multiple named value segments for any number of entities. +Hibernate achieves table-based identifier generation based on its `org.hibernate.id.enhanced.TableGenerator` which defines a table capable of holding multiple named value segments for any number of entities. -.Table generator table structure -==== -[source,sql] ----- -include::{extrasdir}/id/TableGenerator.sql[] ----- -==== The basic idea is that a given table-generator table (`hibernate_sequences` for example) can hold multiple segments of identifier generation values. +[[identifiers-generators-table-unnamed-mapping-example]] .Unnamed table generator ==== [source,java] ---- -include::{extrasdir}/id/UnnamedTable.java[] +include::{sourcedir}/TableGeneratorUnnamedTest.java[tag=identifiers-generators-table-mapping-example, indent=0] +---- + +[source,sql] +---- +include::{extrasdir}/id/identifiers-generators-table-unnamed-mapping-example.sql[] ---- ==== If no table name is given Hibernate assumes an implicit name of `hibernate_sequences`. -Additionally, because no `javax.persistence.TableGenerator#pkColumnValue` is specified, Hibernate will use the default segment (`sequence_name='default'`) from the hibernate_sequences table. + +Additionally, because no `javax.persistence.TableGenerator#pkColumnValue` is specified, +Hibernate will use the default segment (`sequence_name='default'`) from the hibernate_sequences table. + +However, you can configure the table identifier generator using the http://docs.oracle.com/javaee/7/api/javax/persistence/TableGenerator.html[`@TableGenerator`] annotation. + +[[identifiers-generators-table-configured-mapping-example]] +.Configured table generator +==== +[source,java] +---- +include::{sourcedir}/TableGeneratorConfiguredTest.java[tag=identifiers-generators-table-mapping-example, indent=0] +---- + +[source,sql] +---- +include::{extrasdir}/id/identifiers-generators-table-configured-mapping-example.sql[] +---- +==== + +Now, when inserting 3 `Product` entities, Hibernate generates the following statements: + +[[identifiers-generators-table-configured-persist-example]]] +.Configured table generator persist example +==== +[source,java] +---- +include::{sourcedir}/TableGeneratorConfiguredTest.java[tag=identifiers-generators-table-persist-example, indent=0] +---- + +[source,sql] +---- +include::{extrasdir}/id/identifiers-generators-table-configured-persist-example.sql[] +---- +==== [[identifiers-generators-uuid]] ==== Using UUID generation diff --git a/documentation/src/test/java/org/hibernate/userguide/mapping/identifier/ConfiguredSequenceTest.java b/documentation/src/test/java/org/hibernate/userguide/mapping/identifier/SequenceGeneratorConfiguredTest.java similarity index 95% rename from documentation/src/test/java/org/hibernate/userguide/mapping/identifier/ConfiguredSequenceTest.java rename to documentation/src/test/java/org/hibernate/userguide/mapping/identifier/SequenceGeneratorConfiguredTest.java index 4e5bd36c63..09a3debcfa 100644 --- a/documentation/src/test/java/org/hibernate/userguide/mapping/identifier/ConfiguredSequenceTest.java +++ b/documentation/src/test/java/org/hibernate/userguide/mapping/identifier/SequenceGeneratorConfiguredTest.java @@ -25,7 +25,7 @@ import static org.hibernate.testing.transaction.TransactionUtil.doInJPA; * @author Vlad Mihalcea */ @RequiresDialectFeature(DialectChecks.SupportsSequences.class) -public class ConfiguredSequenceTest extends BaseEntityManagerFunctionalTestCase { +public class SequenceGeneratorConfiguredTest extends BaseEntityManagerFunctionalTestCase { @Override protected Class[] getAnnotatedClasses() { diff --git a/documentation/src/test/java/org/hibernate/userguide/mapping/identifier/NamedSequenceTest.java b/documentation/src/test/java/org/hibernate/userguide/mapping/identifier/SequenceGeneratorNamedTest.java similarity index 96% rename from documentation/src/test/java/org/hibernate/userguide/mapping/identifier/NamedSequenceTest.java rename to documentation/src/test/java/org/hibernate/userguide/mapping/identifier/SequenceGeneratorNamedTest.java index 3e5dc9fcd4..e62ba1a29f 100644 --- a/documentation/src/test/java/org/hibernate/userguide/mapping/identifier/NamedSequenceTest.java +++ b/documentation/src/test/java/org/hibernate/userguide/mapping/identifier/SequenceGeneratorNamedTest.java @@ -27,7 +27,7 @@ import static org.hibernate.testing.transaction.TransactionUtil.doInJPA; * @author Vlad Mihalcea */ @RequiresDialectFeature(DialectChecks.SupportsSequences.class) -public class NamedSequenceTest extends BaseEntityManagerFunctionalTestCase { +public class SequenceGeneratorNamedTest extends BaseEntityManagerFunctionalTestCase { @Override protected Class[] getAnnotatedClasses() { diff --git a/documentation/src/test/java/org/hibernate/userguide/mapping/identifier/UnnamedSequenceTest.java b/documentation/src/test/java/org/hibernate/userguide/mapping/identifier/SequenceGeneratorUnnamedTest.java similarity index 95% rename from documentation/src/test/java/org/hibernate/userguide/mapping/identifier/UnnamedSequenceTest.java rename to documentation/src/test/java/org/hibernate/userguide/mapping/identifier/SequenceGeneratorUnnamedTest.java index 35f13dc4c3..3c4bc2dc32 100644 --- a/documentation/src/test/java/org/hibernate/userguide/mapping/identifier/UnnamedSequenceTest.java +++ b/documentation/src/test/java/org/hibernate/userguide/mapping/identifier/SequenceGeneratorUnnamedTest.java @@ -24,7 +24,7 @@ import static org.hibernate.testing.transaction.TransactionUtil.doInJPA; * @author Vlad Mihalcea */ @RequiresDialectFeature(DialectChecks.SupportsSequences.class) -public class UnnamedSequenceTest extends BaseEntityManagerFunctionalTestCase { +public class SequenceGeneratorUnnamedTest extends BaseEntityManagerFunctionalTestCase { @Override protected Class[] getAnnotatedClasses() { diff --git a/documentation/src/test/java/org/hibernate/userguide/mapping/identifier/TableGeneratorConfiguredTest.java b/documentation/src/test/java/org/hibernate/userguide/mapping/identifier/TableGeneratorConfiguredTest.java new file mode 100644 index 0000000000..e05b548f71 --- /dev/null +++ b/documentation/src/test/java/org/hibernate/userguide/mapping/identifier/TableGeneratorConfiguredTest.java @@ -0,0 +1,91 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.userguide.mapping.identifier; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.TableGenerator; + +import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; + +import org.junit.Test; + +import static org.hibernate.testing.transaction.TransactionUtil.doInJPA; + +/** + * @author Vlad Mihalcea + */ +public class TableGeneratorConfiguredTest extends BaseEntityManagerFunctionalTestCase { + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { + Product.class + }; + } + + @Test + public void test() { + doInJPA( this::entityManagerFactory, entityManager -> { + //tag::identifiers-generators-table-persist-example[] + for ( long i = 1; i <= 3; i++ ) { + Product product = new Product(); + product.setName( String.format( "Product %d", i ) ); + entityManager.persist( product ); + } + //end::identifiers-generators-table-persist-example[] + } ); + } + + //tag::identifiers-generators-table-mapping-example[] + @Entity(name = "Product") + public static class Product { + + @Id + @GeneratedValue( + strategy = GenerationType.TABLE, + generator = "table-generator" + ) + @TableGenerator( + name = "table-generator", + table = "table_identifier", + pkColumnName = "table_name", + valueColumnName = "product_id", + allocationSize = 5 + ) + private Long id; + + @Column(name = "product_name") + private String name; + + //Getters and setters are omitted for brevity + + //end::identifiers-generators-table-mapping-example[] + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + //tag::identifiers-generators-table-mapping-example[] + } + //end::identifiers-generators-table-mapping-example[] +} diff --git a/documentation/src/test/java/org/hibernate/userguide/mapping/identifier/TableGeneratorUnnamedTest.java b/documentation/src/test/java/org/hibernate/userguide/mapping/identifier/TableGeneratorUnnamedTest.java new file mode 100644 index 0000000000..d446fcf77d --- /dev/null +++ b/documentation/src/test/java/org/hibernate/userguide/mapping/identifier/TableGeneratorUnnamedTest.java @@ -0,0 +1,85 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.userguide.mapping.identifier; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; + +import org.hibernate.testing.DialectChecks; +import org.hibernate.testing.RequiresDialectFeature; +import org.junit.Test; + +import static org.hibernate.testing.transaction.TransactionUtil.doInJPA; + +/** + * @author Vlad Mihalcea + */ +public class TableGeneratorUnnamedTest extends BaseEntityManagerFunctionalTestCase { + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { + Product.class + }; + } + + @Test + public void test() { + doInJPA( this::entityManagerFactory, entityManager -> { + for ( long i = 1; i <= 5; i++ ) { + if(i % 3 == 0) { + entityManager.flush(); + } + Product product = new Product(); + product.setName( String.format( "Product %d", i ) ); + entityManager.persist( product ); + } + } ); + } + + //tag::identifiers-generators-table-mapping-example[] + @Entity(name = "Product") + public static class Product { + + @Id + @GeneratedValue( + strategy = GenerationType.TABLE + ) + private Long id; + + @Column(name = "product_name") + private String name; + + //Getters and setters are omitted for brevity + + //end::identifiers-generators-table-mapping-example[] + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + //tag::identifiers-generators-table-mapping-example[] + } + //end::identifiers-generators-table-mapping-example[] +} diff --git a/documentation/src/test/resources/log4j.properties b/documentation/src/test/resources/log4j.properties index ca9d7c89f5..49358a1a2d 100644 --- a/documentation/src/test/resources/log4j.properties +++ b/documentation/src/test/resources/log4j.properties @@ -27,6 +27,8 @@ log4j.logger.org.hibernate.SQL=debug ### log JDBC bind parameters ### log4j.logger.org.hibernate.type=trace log4j.logger.org.hibernate.type.descriptor.sql=trace +log4j.logger.org.hibernate.id.enhanced.TableGenerator=trace +log4j.logger.org.hibernate.id.IdentifierGeneratorHelper=trace log4j.logger.org.hibernate.persister.entity.AbstractEntityPersister=trace log4j.logger.org.hibernate.loader.plan.exec.process.internal.EntityReferenceInitializerImpl=trace diff --git a/hibernate-core/src/main/java/org/hibernate/id/IdentifierGeneratorHelper.java b/hibernate-core/src/main/java/org/hibernate/id/IdentifierGeneratorHelper.java index a84b5cefc8..8f021d2417 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/IdentifierGeneratorHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/id/IdentifierGeneratorHelper.java @@ -306,6 +306,7 @@ public final class IdentifierGeneratorHelper { public void bind(PreparedStatement preparedStatement, int position) throws SQLException { // TODO : bind it as 'exact type'? Not sure if that gains us anything... + LOG.tracef( "binding parameter [%s] - [%s]", position, value ); preparedStatement.setLong( position, value ); } diff --git a/hibernate-core/src/main/java/org/hibernate/id/enhanced/TableGenerator.java b/hibernate-core/src/main/java/org/hibernate/id/enhanced/TableGenerator.java index daed218a33..f66aeb56c4 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/enhanced/TableGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/id/enhanced/TableGenerator.java @@ -544,6 +544,7 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab final PreparedStatement insertPS = prepareStatement( connection, insertQuery, statementLogger, statsCollector ); try { + LOG.tracef( "binding parameter [%s] - [%s]", 1, segmentValue ); insertPS.setString( 1, segmentValue ); value.bind( insertPS, 2 ); executeUpdate( insertPS, statsCollector );