HHH-11186 - Add examples for all Hibernate annotations

Document @TableGenerator
This commit is contained in:
Vlad Mihalcea 2017-06-05 17:27:23 +03:00
parent e10653e3a7
commit 5e23b7fd02
15 changed files with 319 additions and 31 deletions

View File

@ -588,7 +588,7 @@ See the <<chapters/query/native/Native.adoc#sql-custom-crud-secondary-table-exam
The http://docs.oracle.com/javaee/7/api/javax/persistence/TableGenerator.html[`@TableGenerator`] annotation is used to specify the database table used by the identity generator of the current annotated entity.
//TODO: Add example
See the <<chapters/domain/identifiers.adoc#identifiers-generators-table-configured-mapping-example,`@TableGenerator` mapping>> section for more info.
[[annotations-jpa-temporal]]
==== `@Temporal`

View File

@ -1,4 +0,0 @@
create table hibernate_sequences(
sequence_name VARCHAR NOT NULL,
next_val INTEGER NOT NULL
)

View File

@ -1,9 +0,0 @@
@Entity
public class MyEntity {
@Id
@GeneratedValue( generation = TABLE )
public Integer id;
...
}

View File

@ -0,0 +1,5 @@
create table table_identifier (
table_name varchar2(255 char) not null,
product_id number(19,0),
primary key (table_name)
)

View File

@ -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]

View File

@ -0,0 +1,5 @@
create table hibernate_sequences (
sequence_name varchar2(255 char) not null,
next_val number(19,0),
primary key (sequence_name)
)

View File

@ -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

View File

@ -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() {

View File

@ -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() {

View File

@ -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() {

View File

@ -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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
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[]
}

View File

@ -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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
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[]
}

View File

@ -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

View File

@ -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 );
}

View File

@ -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 );