improve discussion of foreign key mappings
This commit is contained in:
parent
bb0acd2956
commit
5fd441df70
|
@ -392,7 +392,10 @@ The `@JoinColumn` annotation is used to customize a foreign key column.
|
|||
| `foreignKey` | A `@ForeignKey` annotation specifying the name of the `FOREIGN KEY` constraint
|
||||
|===
|
||||
|
||||
Here we see how to use `@JoinColumn` to define a `@ManyToOne` association which mapping a foreign key column which refers to a non-primary-key `UNIQUE` column of the referenced table.
|
||||
A foreign key column doesn't necessarily have to refer to the primary key of the referenced table.
|
||||
It's quite acceptable for the foreign key to refer to any other unique key of the referenced entity, even to a unique key of a secondary table.
|
||||
|
||||
Here we see how to use `@JoinColumn` to define a `@ManyToOne` association mapping a foreign key column which refers to the `@NaturalId` of `Book`:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
|
@ -402,20 +405,61 @@ class Item {
|
|||
...
|
||||
@ManyToOne(optional=false) // implies nullable=false
|
||||
@JoinColumn(name = "bookIsbn", referencedColumnName = "isbn", // a reference to a non-PK column
|
||||
foreignKey = @ForeignKey(name="ItemsToBooksBySsn")) // supply a name for the FOREIGN KEY constraint
|
||||
foreignKey = @ForeignKey(name="ItemsToBooksBySsn")) // supply a name for the FK constraint
|
||||
Book book;
|
||||
...
|
||||
}
|
||||
----
|
||||
|
||||
In case this is confusing:
|
||||
|
||||
- `bookIsbn` is the name of the foreign key column in the `Items` table,
|
||||
- it refers to a unique key `isbn` in the `Books` table, and
|
||||
- it has a foreign key constraint named `ItemsToBooksBySsn`.
|
||||
|
||||
Note that the `foreignKey` member is completely optional and only affects DDL generation.
|
||||
|
||||
[TIP]
|
||||
// .Foreign key constraint names
|
||||
====
|
||||
Notice the use of `@ForeignKey` to customize the name of the foreign key constraint.
|
||||
If you don't supply a name explicitly, Hibernate will generate a quite ugly name.
|
||||
If you don't supply an explicit name using `@ForeignKey`, Hibernate will generate a quite ugly name.
|
||||
The reason for this is that the maximum length of foreign key names on some databases is extremely constrained, and we need to avoid collisions.
|
||||
To be fair, this is perfectly fine if you're only using the generated DDL for testing.
|
||||
====
|
||||
|
||||
For composite foreign keys we might have multiple `@JoinColumn` annotations:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@Entity
|
||||
@Table(name="Items")
|
||||
class Item {
|
||||
...
|
||||
@ManyToOne(optional=false)
|
||||
@JoinColumn(name = "bookIsbn", referencedColumnName = "isbn")
|
||||
@JoinColumn(name = "bookPrinting", referencedColumnName = "printing")
|
||||
Book book;
|
||||
...
|
||||
}
|
||||
----
|
||||
|
||||
If we need to specify the `@ForeignKey`, this starts to get a bit messy:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@Entity
|
||||
@Table(name="Items")
|
||||
class Item {
|
||||
...
|
||||
@ManyToOne(optional=false)
|
||||
@JoinColumns(value = {@JoinColumn(name = "bookIsbn", referencedColumnName = "isbn"),
|
||||
@JoinColumn(name = "bookPrinting", referencedColumnName = "printing")},
|
||||
foreignKey = @ForeignKey(name="ItemsToBooksBySsn"))
|
||||
Book book;
|
||||
...
|
||||
}
|
||||
----
|
||||
|
||||
For associations mapped to a `@JoinTable`, fetching the association requires two joins, and so we must declare the ``@JoinColumn``s inside the `@JoinTable` annotation:
|
||||
|
||||
[source,java]
|
||||
|
@ -427,13 +471,16 @@ class Book {
|
|||
|
||||
@ManyToMany
|
||||
@JoinTable(joinColumns=@JoinColumn(name="bookId"),
|
||||
inverseJoinColumns=@joinColumn(name="authorId"))
|
||||
inverseJoinColumns=@joinColumn(name="authorId"),
|
||||
foreignKey=@ForeignKey(name="BooksToAuthors"))
|
||||
Set<Author> authors;
|
||||
|
||||
...
|
||||
}
|
||||
----
|
||||
|
||||
Again, the `foreignKey` member is optional.
|
||||
|
||||
[[primary-key-column-mappings]]
|
||||
=== Mapping primary key joins between tables
|
||||
|
||||
|
|
|
@ -173,6 +173,9 @@ public class BasicFormatterImpl implements Formatter {
|
|||
case "into":
|
||||
case "union":
|
||||
case "intersect":
|
||||
case "offset":
|
||||
case "limit":
|
||||
case "fetch":
|
||||
endNewClause();
|
||||
break;
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ public final class HighlightingFormatter implements Formatter {
|
|||
private static final Set<String> KEYWORDS_LOWERCASED = new HashSet<>( new AnsiSqlKeywords().sql2003() );
|
||||
static {
|
||||
// additional keywords not reserved by ANSI SQL 2003
|
||||
KEYWORDS_LOWERCASED.addAll( Arrays.asList( "key", "sequence", "cascade", "increment", "boolean" ) );
|
||||
KEYWORDS_LOWERCASED.addAll( Arrays.asList( "key", "sequence", "cascade", "increment", "boolean", "offset", "next" ) );
|
||||
}
|
||||
|
||||
public static final Formatter INSTANCE =
|
||||
|
|
Loading…
Reference in New Issue