HHH-11186 - Add examples for all Hibernate annotations
Document @UniqueConstraint annotation
This commit is contained in:
parent
87ddf0e74b
commit
c0b0da4282
|
@ -16,6 +16,8 @@ See the <<chapters/domain/access.adoc#access,Access type>> section for more info
|
||||||
|
|
||||||
The http://docs.oracle.com/javaee/7/api/javax/persistence/AssociationOverride.html[`@AssociationOverride`] annotation is used to override an association mapping (e.g. `@ManyToOne`, `@OneToOne`, `@OneToMany`, `@ManyToMany`) inherited from a mapped superclass or an embeddable.
|
The http://docs.oracle.com/javaee/7/api/javax/persistence/AssociationOverride.html[`@AssociationOverride`] annotation is used to override an association mapping (e.g. `@ManyToOne`, `@OneToOne`, `@OneToMany`, `@ManyToMany`) inherited from a mapped superclass or an embeddable.
|
||||||
|
|
||||||
|
//TODO: Add example
|
||||||
|
|
||||||
[[annotations-jpa-associationoverrides]]
|
[[annotations-jpa-associationoverrides]]
|
||||||
==== `@AssociationOverrides`
|
==== `@AssociationOverrides`
|
||||||
|
|
||||||
|
@ -26,6 +28,8 @@ The http://docs.oracle.com/javaee/7/api/javax/persistence/AssociationOverrides.h
|
||||||
|
|
||||||
The http://docs.oracle.com/javaee/7/api/javax/persistence/AttributeOverride.html[`@AttributeOverride`] annotation is used to override an attribute mapping inherited from a mapped superclass or an embeddable.
|
The http://docs.oracle.com/javaee/7/api/javax/persistence/AttributeOverride.html[`@AttributeOverride`] annotation is used to override an attribute mapping inherited from a mapped superclass or an embeddable.
|
||||||
|
|
||||||
|
//TODO: Add example
|
||||||
|
|
||||||
[[annotations-jpa-attributeoverrides]]
|
[[annotations-jpa-attributeoverrides]]
|
||||||
==== `@AttributeOverrides`
|
==== `@AttributeOverrides`
|
||||||
|
|
||||||
|
@ -75,6 +79,8 @@ See the <<chapters/query/native/Native.adoc#sql-composite-key-entity-association
|
||||||
|
|
||||||
The http://docs.oracle.com/javaee/7/api/javax/persistence/ConstructorResult.html[`@ConstructorResult`] annotation is used in conjunction with the <<annotations-jpa-sqlresultsetmapping>> annotations to map columns of a given SELECT query to a certain object constructor.
|
The http://docs.oracle.com/javaee/7/api/javax/persistence/ConstructorResult.html[`@ConstructorResult`] annotation is used in conjunction with the <<annotations-jpa-sqlresultsetmapping>> annotations to map columns of a given SELECT query to a certain object constructor.
|
||||||
|
|
||||||
|
//TODO: Add example
|
||||||
|
|
||||||
[[annotations-jpa-convert]]
|
[[annotations-jpa-convert]]
|
||||||
==== `@Convert`
|
==== `@Convert`
|
||||||
|
|
||||||
|
@ -176,11 +182,15 @@ See the <<chapters/domain/basic_types.adoc#basic-enums-Enumerated, `@Enumerated`
|
||||||
|
|
||||||
The http://docs.oracle.com/javaee/7/api/javax/persistence/ExcludeDefaultListeners.html[`@ExcludeDefaultListeners`] annotation is used to specify that the current annotated entity skips the invocation of any default listener.
|
The http://docs.oracle.com/javaee/7/api/javax/persistence/ExcludeDefaultListeners.html[`@ExcludeDefaultListeners`] annotation is used to specify that the current annotated entity skips the invocation of any default listener.
|
||||||
|
|
||||||
|
//TODO: Add example
|
||||||
|
|
||||||
[[annotations-jpa-excludesuperclasslisteners]]
|
[[annotations-jpa-excludesuperclasslisteners]]
|
||||||
==== `@ExcludeSuperclassListeners`
|
==== `@ExcludeSuperclassListeners`
|
||||||
|
|
||||||
The http://docs.oracle.com/javaee/7/api/javax/persistence/ExcludeSuperclassListeners.html[`@ExcludeSuperclassListeners`] annotation is used to specify that the current annotated entity skips the invocation of listeners declared by its superclass.
|
The http://docs.oracle.com/javaee/7/api/javax/persistence/ExcludeSuperclassListeners.html[`@ExcludeSuperclassListeners`] annotation is used to specify that the current annotated entity skips the invocation of listeners declared by its superclass.
|
||||||
|
|
||||||
|
//TODO: Add example
|
||||||
|
|
||||||
[[annotations-jpa-fieldresult]]
|
[[annotations-jpa-fieldresult]]
|
||||||
==== `@FieldResult`
|
==== `@FieldResult`
|
||||||
|
|
||||||
|
@ -225,6 +235,8 @@ See the <<chapters/domain/identifiers.adoc#identifiers-composite-nonaggregated,C
|
||||||
|
|
||||||
The http://docs.oracle.com/javaee/7/api/javax/persistence/Index.html[`@Index`] annotation is used by the automated schema generation tool to create a database index.
|
The http://docs.oracle.com/javaee/7/api/javax/persistence/Index.html[`@Index`] annotation is used by the automated schema generation tool to create a database index.
|
||||||
|
|
||||||
|
//TODO: Add example
|
||||||
|
|
||||||
[[annotations-jpa-inheritance]]
|
[[annotations-jpa-inheritance]]
|
||||||
==== `@Inheritance`
|
==== `@Inheritance`
|
||||||
|
|
||||||
|
@ -244,6 +256,8 @@ See the <<chapters/domain/associations.adoc#associations-many-to-one-example,`@M
|
||||||
|
|
||||||
The http://docs.oracle.com/javaee/7/api/javax/persistence/JoinColumns.html[`@JoinColumns`] annotation is used to group multiple <<annotations-jpa-joincolumn>> annotations, which are used when mapping entity association or an embeddable collection using a composite identifier
|
The http://docs.oracle.com/javaee/7/api/javax/persistence/JoinColumns.html[`@JoinColumns`] annotation is used to group multiple <<annotations-jpa-joincolumn>> annotations, which are used when mapping entity association or an embeddable collection using a composite identifier
|
||||||
|
|
||||||
|
//TODO: Add example
|
||||||
|
|
||||||
[[annotations-jpa-jointable]]
|
[[annotations-jpa-jointable]]
|
||||||
==== `@JoinTable`
|
==== `@JoinTable`
|
||||||
|
|
||||||
|
@ -284,11 +298,15 @@ See the <<chapters/domain/collections.adoc#collections-map-unidirectional-exampl
|
||||||
|
|
||||||
The http://docs.oracle.com/javaee/7/api/javax/persistence/MapKeyClass.html[`@MapKeyClass`] annotation is used to specify the type of the map key of a `java.util.Map` associations.
|
The http://docs.oracle.com/javaee/7/api/javax/persistence/MapKeyClass.html[`@MapKeyClass`] annotation is used to specify the type of the map key of a `java.util.Map` associations.
|
||||||
|
|
||||||
|
//TODO: Add example
|
||||||
|
|
||||||
[[annotations-jpa-mapkeycolumn]]
|
[[annotations-jpa-mapkeycolumn]]
|
||||||
==== `@MapKeyColumn`
|
==== `@MapKeyColumn`
|
||||||
|
|
||||||
The http://docs.oracle.com/javaee/7/api/javax/persistence/MapKeyColumn.html[`@MapKeyColumn`] annotation is used to specify the database column which stores the key of a `java.util.Map` association for which the map key is a basic type.
|
The http://docs.oracle.com/javaee/7/api/javax/persistence/MapKeyColumn.html[`@MapKeyColumn`] annotation is used to specify the database column which stores the key of a `java.util.Map` association for which the map key is a basic type.
|
||||||
|
|
||||||
|
//TODO: Add example
|
||||||
|
|
||||||
[[annotations-jpa-mapkeyenumerated]]
|
[[annotations-jpa-mapkeyenumerated]]
|
||||||
==== `@MapKeyEnumerated`
|
==== `@MapKeyEnumerated`
|
||||||
|
|
||||||
|
@ -309,6 +327,8 @@ See the <<chapters/domain/collections.adoc#collections-map-value-type-entity-key
|
||||||
|
|
||||||
The http://docs.oracle.com/javaee/7/api/javax/persistence/MapKeyJoinColumns.html[`@MapKeyJoinColumns`] annotation is used to group several <<annotations-jpa-mapkeyjoincolumn>> mappings when the `java.util.Map` association key uses a composite identifier.
|
The http://docs.oracle.com/javaee/7/api/javax/persistence/MapKeyJoinColumns.html[`@MapKeyJoinColumns`] annotation is used to group several <<annotations-jpa-mapkeyjoincolumn>> mappings when the `java.util.Map` association key uses a composite identifier.
|
||||||
|
|
||||||
|
//TODO: Add example
|
||||||
|
|
||||||
[[annotations-jpa-mapkeytemporal]]
|
[[annotations-jpa-mapkeytemporal]]
|
||||||
==== `@MapKeyTemporal`
|
==== `@MapKeyTemporal`
|
||||||
|
|
||||||
|
@ -373,6 +393,8 @@ The http://docs.oracle.com/javaee/7/api/javax/persistence/NamedQueries.html[`@Na
|
||||||
|
|
||||||
The http://docs.oracle.com/javaee/7/api/javax/persistence/NamedQuery.html[`@NamedQuery`] annotation is used to specify a JPQL query that can be retrieved later by its name.
|
The http://docs.oracle.com/javaee/7/api/javax/persistence/NamedQuery.html[`@NamedQuery`] annotation is used to specify a JPQL query that can be retrieved later by its name.
|
||||||
|
|
||||||
|
//TODO: Add example
|
||||||
|
|
||||||
[[annotations-jpa-namedstoredprocedurequeries]]
|
[[annotations-jpa-namedstoredprocedurequeries]]
|
||||||
==== `@NamedStoredProcedureQueries`
|
==== `@NamedStoredProcedureQueries`
|
||||||
|
|
||||||
|
@ -383,11 +405,15 @@ The http://docs.oracle.com/javaee/7/api/javax/persistence/NamedStoredProcedureQu
|
||||||
|
|
||||||
The http://docs.oracle.com/javaee/7/api/javax/persistence/NamedStoredProcedureQuery.html[`@NamedStoredProcedureQuery`] annotation is used to specify a stored procedure query that can be retrieved later by its name.
|
The http://docs.oracle.com/javaee/7/api/javax/persistence/NamedStoredProcedureQuery.html[`@NamedStoredProcedureQuery`] annotation is used to specify a stored procedure query that can be retrieved later by its name.
|
||||||
|
|
||||||
|
//TODO: Add example
|
||||||
|
|
||||||
[[annotations-jpa-namedsubgraph]]
|
[[annotations-jpa-namedsubgraph]]
|
||||||
==== `@NamedSubgraph`
|
==== `@NamedSubgraph`
|
||||||
|
|
||||||
The http://docs.oracle.com/javaee/7/api/javax/persistence/NamedSubgraph.html[`@NamedSubgraph`] annotation used to specify a subgraph in an Entity Graph.
|
The http://docs.oracle.com/javaee/7/api/javax/persistence/NamedSubgraph.html[`@NamedSubgraph`] annotation used to specify a subgraph in an Entity Graph.
|
||||||
|
|
||||||
|
//TODO: Add example
|
||||||
|
|
||||||
[[annotations-jpa-onetomany]]
|
[[annotations-jpa-onetomany]]
|
||||||
==== `@OneToMany`
|
==== `@OneToMany`
|
||||||
|
|
||||||
|
@ -421,6 +447,8 @@ See the <<chapters/domain/collections.adoc#collections-unidirectional-ordered-li
|
||||||
|
|
||||||
The http://docs.oracle.com/javaee/7/api/javax/persistence/PersistenceContext.html[`@PersistenceContext`] annotation is used to specify the `EntityManager` that needs to be injected as a dependency.
|
The http://docs.oracle.com/javaee/7/api/javax/persistence/PersistenceContext.html[`@PersistenceContext`] annotation is used to specify the `EntityManager` that needs to be injected as a dependency.
|
||||||
|
|
||||||
|
//TODO: Add example
|
||||||
|
|
||||||
[[annotations-jpa-persistencecontexts]]
|
[[annotations-jpa-persistencecontexts]]
|
||||||
==== `@PersistenceContexts`
|
==== `@PersistenceContexts`
|
||||||
|
|
||||||
|
@ -431,11 +459,15 @@ The http://docs.oracle.com/javaee/7/api/javax/persistence/PersistenceContexts.ht
|
||||||
|
|
||||||
The http://docs.oracle.com/javaee/7/api/javax/persistence/PersistenceProperty.html[`@PersistenceProperty`] annotation is used by the <<annotations-jpa-persistencecontext>> annotation to declare JPA provider properties that are passed to the underlying container when the `EntityManager` instance is created.
|
The http://docs.oracle.com/javaee/7/api/javax/persistence/PersistenceProperty.html[`@PersistenceProperty`] annotation is used by the <<annotations-jpa-persistencecontext>> annotation to declare JPA provider properties that are passed to the underlying container when the `EntityManager` instance is created.
|
||||||
|
|
||||||
|
//TODO: Add example
|
||||||
|
|
||||||
[[annotations-jpa-persistenceunit]]
|
[[annotations-jpa-persistenceunit]]
|
||||||
==== `@PersistenceUnit`
|
==== `@PersistenceUnit`
|
||||||
|
|
||||||
The http://docs.oracle.com/javaee/7/api/javax/persistence/PersistenceUnit.html[`@PersistenceUnit`] annotation is used to specify the `EntityManagerFactory` that needs to be injected as a dependency.
|
The http://docs.oracle.com/javaee/7/api/javax/persistence/PersistenceUnit.html[`@PersistenceUnit`] annotation is used to specify the `EntityManagerFactory` that needs to be injected as a dependency.
|
||||||
|
|
||||||
|
//TODO: Add example
|
||||||
|
|
||||||
[[annotations-jpa-persistenceunits]]
|
[[annotations-jpa-persistenceunits]]
|
||||||
==== `@PersistenceUnits`
|
==== `@PersistenceUnits`
|
||||||
|
|
||||||
|
@ -508,6 +540,8 @@ The http://docs.oracle.com/javaee/7/api/javax/persistence/PrimaryKeyJoinColumns.
|
||||||
|
|
||||||
The http://docs.oracle.com/javaee/7/api/javax/persistence/QueryHint.html[`@QueryHint`] annotation is used to specify a JPA provider hint used by a `@NamedQuery` or a `@NamedNativeQuery` annotation.
|
The http://docs.oracle.com/javaee/7/api/javax/persistence/QueryHint.html[`@QueryHint`] annotation is used to specify a JPA provider hint used by a `@NamedQuery` or a `@NamedNativeQuery` annotation.
|
||||||
|
|
||||||
|
//TODO: Add example
|
||||||
|
|
||||||
[[annotations-jpa-secondarytable]]
|
[[annotations-jpa-secondarytable]]
|
||||||
==== `@SecondaryTable`
|
==== `@SecondaryTable`
|
||||||
|
|
||||||
|
@ -525,6 +559,8 @@ The http://docs.oracle.com/javaee/7/api/javax/persistence/SecondaryTables.html[`
|
||||||
|
|
||||||
The http://docs.oracle.com/javaee/7/api/javax/persistence/SequenceGenerator.html[`@SequenceGenerator`] annotation is used to specify the database sequence used by the identifier generator of the current annotated entity.
|
The http://docs.oracle.com/javaee/7/api/javax/persistence/SequenceGenerator.html[`@SequenceGenerator`] annotation is used to specify the database sequence used by the identifier generator of the current annotated entity.
|
||||||
|
|
||||||
|
//TODO: Add example
|
||||||
|
|
||||||
[[annotations-jpa-sqlresultsetmapping]]
|
[[annotations-jpa-sqlresultsetmapping]]
|
||||||
==== `@SqlResultSetMapping`
|
==== `@SqlResultSetMapping`
|
||||||
|
|
||||||
|
@ -542,6 +578,8 @@ The http://docs.oracle.com/javaee/7/api/javax/persistence/SqlResultSetMappings.h
|
||||||
|
|
||||||
The http://docs.oracle.com/javaee/7/api/javax/persistence/StoredProcedureParameter.html[`@StoredProcedureParameter`] annotation is used to specify a parameter of a <<annotations-jpa-namedstoredprocedurequery>>.
|
The http://docs.oracle.com/javaee/7/api/javax/persistence/StoredProcedureParameter.html[`@StoredProcedureParameter`] annotation is used to specify a parameter of a <<annotations-jpa-namedstoredprocedurequery>>.
|
||||||
|
|
||||||
|
//TODO: Add example
|
||||||
|
|
||||||
[[annotations-jpa-table]]
|
[[annotations-jpa-table]]
|
||||||
==== `@Table`
|
==== `@Table`
|
||||||
|
|
||||||
|
@ -554,6 +592,8 @@ 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.
|
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
|
||||||
|
|
||||||
[[annotations-jpa-temporal]]
|
[[annotations-jpa-temporal]]
|
||||||
==== `@Temporal`
|
==== `@Temporal`
|
||||||
|
|
||||||
|
@ -573,6 +613,8 @@ See the <<chapters/events/Events.adoc#events-jpa-callbacks-example, `@Transient`
|
||||||
|
|
||||||
The http://docs.oracle.com/javaee/7/api/javax/persistence/UniqueConstraint.html[`@UniqueConstraint`] annotation is used to specify a unique constraint to be included by the automated schema generator for the primary or secondary table associated with the current annotated entity.
|
The http://docs.oracle.com/javaee/7/api/javax/persistence/UniqueConstraint.html[`@UniqueConstraint`] annotation is used to specify a unique constraint to be included by the automated schema generator for the primary or secondary table associated with the current annotated entity.
|
||||||
|
|
||||||
|
See the <<chapters/schema/Schema.adoc#schema-generation-columns-unique-constraint, Columns unique constraint>> chapter for more info.
|
||||||
|
|
||||||
[[annotations-jpa-version]]
|
[[annotations-jpa-version]]
|
||||||
==== `@Version`
|
==== `@Version`
|
||||||
|
|
||||||
|
|
|
@ -159,3 +159,43 @@ include::{sourcedir}/ColumnDefaultTest.java[tag=schema-generation-column-default
|
||||||
include::{extrasdir}/schema-generation-column-default-value-persist-example.sql[]
|
include::{extrasdir}/schema-generation-column-default-value-persist-example.sql[]
|
||||||
----
|
----
|
||||||
====
|
====
|
||||||
|
|
||||||
|
[[schema-generation-columns-unique-constraint]]
|
||||||
|
=== Columns unique constraint
|
||||||
|
|
||||||
|
The http://docs.oracle.com/javaee/7/api/javax/persistence/UniqueConstraint.html[`@UniqueConstraint`] annotation is used to specify a unique constraint to be included by the automated schema generator for the primary or secondary table associated with the current annotated entity.
|
||||||
|
|
||||||
|
Considering the following entity mapping, Hibernate generates the unique constraint DDL when creating the database schema:
|
||||||
|
|
||||||
|
[[schema-generation-columns-unique-constraint-mapping-example]]
|
||||||
|
.`@UniqueConstraint` mapping example
|
||||||
|
====
|
||||||
|
[source, JAVA, indent=0]
|
||||||
|
----
|
||||||
|
include::{sourcedir}/UniqueConstraintTest.java[tag=schema-generation-columns-unique-constraint-mapping-example]
|
||||||
|
----
|
||||||
|
|
||||||
|
[source, SQL, indent=0]
|
||||||
|
----
|
||||||
|
include::{extrasdir}/schema-generation-columns-unique-constraint-mapping-example.sql[]
|
||||||
|
----
|
||||||
|
====
|
||||||
|
|
||||||
|
With the `uk_book_title_author` unique constraint in place,
|
||||||
|
it's no longer possible to add two books with the same title and for the same author.
|
||||||
|
|
||||||
|
[[schema-generation-columns-unique-constraint-persist-example]]
|
||||||
|
.`@UniqueConstraintTest` persist example
|
||||||
|
====
|
||||||
|
[source, JAVA, indent=0]
|
||||||
|
----
|
||||||
|
include::{sourcedir}/UniqueConstraintTest.java[tag=schema-generation-columns-unique-constraint-persist-example]
|
||||||
|
----
|
||||||
|
|
||||||
|
[source, SQL, indent=0]
|
||||||
|
----
|
||||||
|
include::{extrasdir}/schema-generation-columns-unique-constraint-persist-example.sql[]
|
||||||
|
----
|
||||||
|
====
|
||||||
|
|
||||||
|
The second INSERT statement fails because of the unique coonstraint violation.
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
create table author (
|
||||||
|
id bigint not null,
|
||||||
|
firstName varchar(255),
|
||||||
|
lastName varchar(255),
|
||||||
|
primary key (id)
|
||||||
|
)
|
||||||
|
|
||||||
|
create table book (
|
||||||
|
id bigint not null,
|
||||||
|
title varchar(255),
|
||||||
|
author_id bigint,
|
||||||
|
primary key (id)
|
||||||
|
)
|
||||||
|
|
||||||
|
alter table book
|
||||||
|
add constraint uk_book_title_author
|
||||||
|
unique (title, author_id)
|
||||||
|
|
||||||
|
alter table book
|
||||||
|
add constraint fk_book_author_id
|
||||||
|
foreign key (author_id)
|
||||||
|
references author
|
|
@ -0,0 +1,35 @@
|
||||||
|
insert
|
||||||
|
into
|
||||||
|
author
|
||||||
|
(firstName, lastName, id)
|
||||||
|
values
|
||||||
|
(?, ?, ?)
|
||||||
|
|
||||||
|
-- binding parameter [1] as [VARCHAR] - [Vlad]
|
||||||
|
-- binding parameter [2] as [VARCHAR] - [Mihalcea]
|
||||||
|
-- binding parameter [3] as [BIGINT] - [1]
|
||||||
|
|
||||||
|
insert
|
||||||
|
into
|
||||||
|
book
|
||||||
|
(author_id, title, id)
|
||||||
|
values
|
||||||
|
(?, ?, ?)
|
||||||
|
|
||||||
|
-- binding parameter [1] as [BIGINT] - [1]
|
||||||
|
-- binding parameter [2] as [VARCHAR] - [High-Performance Java Persistence]
|
||||||
|
-- binding parameter [3] as [BIGINT] - [2]
|
||||||
|
|
||||||
|
insert
|
||||||
|
into
|
||||||
|
book
|
||||||
|
(author_id, title, id)
|
||||||
|
values
|
||||||
|
(?, ?, ?)
|
||||||
|
|
||||||
|
-- binding parameter [1] as [BIGINT] - [1]
|
||||||
|
-- binding parameter [2] as [VARCHAR] - [High-Performance Java Persistence]
|
||||||
|
-- binding parameter [3] as [BIGINT] - [3]
|
||||||
|
|
||||||
|
-- SQL Error: 23505, SQLState: 23505
|
||||||
|
-- Unique index or primary key violation: "UK_BOOK_TITLE_AUTHOR_INDEX_1 ON PUBLIC.BOOK(TITLE, AUTHOR_ID) VALUES ( /* key:1 */ 3, 'High-Performance Java Persistence', 1)";
|
|
@ -0,0 +1,175 @@
|
||||||
|
/*
|
||||||
|
* 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.schema;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.FetchType;
|
||||||
|
import javax.persistence.ForeignKey;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.JoinColumn;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
import javax.persistence.UniqueConstraint;
|
||||||
|
|
||||||
|
import org.hibernate.annotations.ColumnDefault;
|
||||||
|
import org.hibernate.annotations.DynamicInsert;
|
||||||
|
import org.hibernate.exception.ConstraintViolationException;
|
||||||
|
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
||||||
|
|
||||||
|
import org.hibernate.testing.util.ExceptionUtil;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Vlad Mihalcea
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class UniqueConstraintTest extends BaseEntityManagerFunctionalTestCase {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<?>[] getAnnotatedClasses() {
|
||||||
|
return new Class<?>[] {
|
||||||
|
Book.class,
|
||||||
|
Author.class,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test() {
|
||||||
|
//tag::schema-generation-columns-unique-constraint-persist-example[]
|
||||||
|
Author _author = doInJPA( this::entityManagerFactory, entityManager -> {
|
||||||
|
Author author = new Author();
|
||||||
|
author.setFirstName( "Vlad" );
|
||||||
|
author.setLastName( "Mihalcea" );
|
||||||
|
entityManager.persist( author );
|
||||||
|
|
||||||
|
Book book = new Book();
|
||||||
|
book.setTitle( "High-Performance Java Persistence" );
|
||||||
|
book.setAuthor( author );
|
||||||
|
entityManager.persist( book );
|
||||||
|
|
||||||
|
return author;
|
||||||
|
} );
|
||||||
|
|
||||||
|
try {
|
||||||
|
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||||
|
Book book = new Book();
|
||||||
|
book.setTitle( "High-Performance Java Persistence" );
|
||||||
|
book.setAuthor( _author );
|
||||||
|
entityManager.persist( book );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
catch (Exception expected) {
|
||||||
|
assertNotNull( ExceptionUtil.findCause( expected, ConstraintViolationException.class ) );
|
||||||
|
}
|
||||||
|
//end::schema-generation-columns-unique-constraint-persist-example[]
|
||||||
|
}
|
||||||
|
|
||||||
|
//tag::schema-generation-columns-unique-constraint-mapping-example[]
|
||||||
|
@Entity
|
||||||
|
@Table(
|
||||||
|
name = "book",
|
||||||
|
uniqueConstraints = @UniqueConstraint(
|
||||||
|
name = "uk_book_title_author",
|
||||||
|
columnNames = {
|
||||||
|
"title",
|
||||||
|
"author_id"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
public static class Book {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private String title;
|
||||||
|
|
||||||
|
@ManyToOne(fetch = FetchType.LAZY)
|
||||||
|
@JoinColumn(
|
||||||
|
name = "author_id",
|
||||||
|
foreignKey = @ForeignKey(name = "fk_book_author_id")
|
||||||
|
)
|
||||||
|
private Author author;
|
||||||
|
|
||||||
|
//Getter and setters omitted for brevity
|
||||||
|
//end::schema-generation-columns-unique-constraint-mapping-example[]
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTitle() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTitle(String title) {
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Author getAuthor() {
|
||||||
|
return author;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAuthor(Author author) {
|
||||||
|
this.author = author;
|
||||||
|
}
|
||||||
|
|
||||||
|
//tag::schema-generation-columns-unique-constraint-mapping-example[]
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "author")
|
||||||
|
public static class Author {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private String firstName;
|
||||||
|
|
||||||
|
private String lastName;
|
||||||
|
|
||||||
|
//Getter and setters omitted for brevity
|
||||||
|
//end::schema-generation-columns-unique-constraint-mapping-example[]
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFirstName() {
|
||||||
|
return firstName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFirstName(String firstName) {
|
||||||
|
this.firstName = firstName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLastName() {
|
||||||
|
return lastName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLastName(String lastName) {
|
||||||
|
this.lastName = lastName;
|
||||||
|
}
|
||||||
|
|
||||||
|
//tag::schema-generation-columns-unique-constraint-mapping-example[]
|
||||||
|
}
|
||||||
|
//end::schema-generation-columns-unique-constraint-mapping-example[]
|
||||||
|
}
|
|
@ -13,7 +13,6 @@ hibernate.connection.password @jdbc.pass@
|
||||||
|
|
||||||
hibernate.connection.pool_size 5
|
hibernate.connection.pool_size 5
|
||||||
|
|
||||||
hibernate.show_sql true
|
|
||||||
hibernate.format_sql true
|
hibernate.format_sql true
|
||||||
hibernate.max_fetch_depth 5
|
hibernate.max_fetch_depth 5
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,22 @@ public class ExceptionUtil {
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a specific cause.
|
||||||
|
*
|
||||||
|
* @param t exception
|
||||||
|
* @param causeClass cause type
|
||||||
|
*
|
||||||
|
* @return exception root cause
|
||||||
|
*/
|
||||||
|
public static Throwable findCause(Throwable t, Class<? extends Throwable> causeClass) {
|
||||||
|
Throwable cause = t.getCause();
|
||||||
|
if ( cause != null && !causeClass.equals( cause.getClass() ) ) {
|
||||||
|
return ( cause != t ) ? findCause( cause, causeClass ) : null;
|
||||||
|
}
|
||||||
|
return cause;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Was the given exception caused by a SQL lock timeout?
|
* Was the given exception caused by a SQL lock timeout?
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue