Skip to content

Commit 0609471

Browse files
committed
HHH-10826 Auxiliary Database Object no longer documented
HHH-10334 @formula annotation javadoc contains database dependent sample usage Created a new section related to automatic schema generation
1 parent 7096f22 commit 0609471

File tree

9 files changed

+354
-2
lines changed

9 files changed

+354
-2
lines changed

documentation/src/main/asciidoc/userguide/Hibernate_User_Guide.adoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ include::Preface.adoc[]
1010
include::chapters/architecture/Architecture.adoc[]
1111
include::chapters/domain/DomainModel.adoc[]
1212
include::chapters/bootstrap/Bootstrap.adoc[]
13+
include::chapters/schema/Schema.adoc[]
1314
include::chapters/pc/PersistenceContext.adoc[]
1415
include::chapters/flushing/Flushing.adoc[]
1516
include::chapters/jdbc/Database_Access.adoc[]

documentation/src/main/asciidoc/userguide/appendices/Configurations.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -555,7 +555,7 @@ Hibernate historically also accepted `hibernate.hbm2ddl.import_files` for a simi
555555
Comma-separated names of the optional files containing SQL DML statements executed during the `SessionFactory` creation.
556556
File order matters, the statements of a give file are executed before the statements of the following one.
557557

558-
These statements are only executed if the schema is created, meaning that `hibernate.hbm2ddl.auto` is set to `create` or `create-drop`.
558+
These statements are only executed if the schema is created, meaning that `hibernate.hbm2ddl.auto` is set to `create`, `create-drop`, or `update`.
559559
`javax.persistence.schema-generation.create-script-source` / `javax.persistence.schema-generation.drop-script-source` should be preferred.
560560

561561
|`javax.persistence.sql-load-script-source` | |

documentation/src/main/asciidoc/userguide/chapters/domain/basic_types.adoc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1191,6 +1191,11 @@ include::{extrasdir}/basic/mapping-column-read-and-write-composite-type-persiste
11911191
Sometimes, you want the Database to do some computation for you rather than in the JVM, you might also create some kind of virtual column.
11921192
You can use a SQL fragment (aka formula) instead of mapping a property into a column. This kind of property is read only (its value is calculated by your formula fragment)
11931193

1194+
[NOTE]
1195+
====
1196+
You should be aware that the `@Formula` annotation takes a native SQL clause which can affect database portability.
1197+
====
1198+
11941199
[[mapping-column-formula-example]]
11951200
.`@Formula` mapping usage
11961201
====
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
[[schema-generation]]
2+
== Schema generation
3+
:sourcedir: ../../../../../test/java/org/hibernate/userguide/schema
4+
:extrasdir: extras
5+
:resourcesdir: ../../../../../test/resources
6+
7+
8+
Hibernate allows you to generate the database from the entity mappings.
9+
10+
[TIP]
11+
====
12+
Although the automatic schema generation is very useful for testing and prototyping purposes, in a production environment,
13+
it's much more flexible to manage the schema using incremental migration scripts.
14+
====
15+
16+
Traditionally, the process of generating schema from entity mapping has been called `HBM2DDL`.
17+
To get a list of Hibernate-native and JPA-specific configuration properties consider reading the <<appendices/Configurations.adoc#configurations-hbmddl,Configurations>> section.
18+
19+
Considering the following Domain Model:
20+
21+
[[schema-generation-domain-model-example]]
22+
.Schema generation Domain Model
23+
====
24+
[source, JAVA, indent=0]
25+
----
26+
include::{sourcedir}/SchemaGenerationTest.java[tags=schema-generation-domain-model-example]
27+
----
28+
====
29+
30+
If the `hibernate.hbm2ddl.auto` configuration is set to `create`, Hibernate is going to generate the following database schema:
31+
32+
[[sql-schema-generation-domain-model-example]]
33+
.Auto-generated database schema
34+
====
35+
[source, SQL, indent=0]
36+
----
37+
include::{extrasdir}/sql-schema-generation-domain-model-example.sql[]
38+
----
39+
====
40+
41+
=== Importing script files
42+
43+
To customize the schema generation process, the `hibernate.hbm2ddl.import_files` configuration property must be used to provide other scripts files that Hibernate can use when the `SessionFactory` is started.
44+
45+
For instance, considering the following `schema-generation.sql` import file:
46+
47+
[[schema-generation-import-file-example]]
48+
.Schema generation import file
49+
====
50+
[source, JAVA, indent=0]
51+
----
52+
include::{resourcesdir}/schema-generation.sql[]
53+
----
54+
====
55+
56+
If we configure Hibernate to import the script above:
57+
58+
[[schema-generation-import-file-configuration-example]]
59+
.Enabling query cache
60+
====
61+
[source, XML, indent=0]
62+
----
63+
<property
64+
name="hibernate.hbm2ddl.import_files"
65+
value="schema-generation.sql" />
66+
----
67+
====
68+
69+
Hibernate is going to execute the script file after the schema is automatically generated.
70+
71+
=== Database objects
72+
73+
Hibernate allows you to customize the schema generation process via the HBM `database-object` element.
74+
75+
Considering the following HBM mapping:
76+
77+
[[schema-generation-database-object-example]]
78+
.Schema generation HBM database-object
79+
====
80+
[source, JAVA, indent=0]
81+
----
82+
include::{sourcedir}/SchemaGenerationTest.hbm.xml[]
83+
----
84+
====
85+
86+
When the `SessionFactory` is bootstrapped, Hibernate is going to execute the `database-object`, therefore creating the `sp_count_books` funtion.
87+
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
create table Customer (
2+
id integer not null,
3+
accountsPayableXrefId binary,
4+
image blob,
5+
name varchar(255),
6+
primary key (id)
7+
)
8+
9+
create table Book (
10+
id bigint not null,
11+
isbn varchar(255),
12+
title varchar(255),
13+
author_id bigint,
14+
primary key (id)
15+
)
16+
17+
create table Person (
18+
id bigint not null,
19+
name varchar(255),
20+
primary key (id)
21+
)
22+
23+
alter table Book
24+
add constraint UK_u31e1frmjp9mxf8k8tmp990i unique (isbn)
25+
26+
alter table Book
27+
add constraint FKrxrgiajod1le3gii8whx2doie
28+
foreign key (author_id)
29+
references Person
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?xml version="1.0"?>
2+
<!DOCTYPE hibernate-mapping PUBLIC
3+
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
4+
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd" >
5+
6+
<hibernate-mapping>
7+
<database-object>
8+
<create>
9+
CREATE OR REPLACE FUNCTION sp_count_books(
10+
IN authorId bigint,
11+
OUT bookCount bigint)
12+
RETURNS bigint AS
13+
$BODY$
14+
BEGIN
15+
SELECT COUNT(*) INTO bookCount
16+
FROM book
17+
WHERE author_id = authorId;
18+
END;
19+
$BODY$
20+
LANGUAGE plpgsql;
21+
</create>
22+
<drop></drop>
23+
<dialect-scope name="org.hibernate.dialect.PostgreSQL95Dialect" />
24+
</database-object>
25+
</hibernate-mapping>
Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
/*
2+
* Hibernate, Relational Persistence for Idiomatic Java
3+
*
4+
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
5+
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
6+
*/
7+
package org.hibernate.userguide.schema;
8+
9+
import java.sql.Blob;
10+
import java.util.ArrayList;
11+
import java.util.List;
12+
import java.util.Map;
13+
import java.util.UUID;
14+
import javax.persistence.Basic;
15+
import javax.persistence.Entity;
16+
import javax.persistence.FetchType;
17+
import javax.persistence.Id;
18+
import javax.persistence.Lob;
19+
import javax.persistence.ManyToOne;
20+
import javax.persistence.OneToMany;
21+
22+
import org.hibernate.annotations.LazyGroup;
23+
import org.hibernate.annotations.NaturalId;
24+
import org.hibernate.cfg.AvailableSettings;
25+
import org.hibernate.dialect.H2Dialect;
26+
import org.hibernate.dialect.PostgreSQL81Dialect;
27+
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
28+
29+
import org.hibernate.testing.RequiresDialect;
30+
import org.junit.Test;
31+
32+
/**
33+
* @author Vlad Mihalcea
34+
*/
35+
public class SchemaGenerationTest extends BaseEntityManagerFunctionalTestCase {
36+
37+
@Override
38+
protected Class<?>[] getAnnotatedClasses() {
39+
return new Class<?>[] {
40+
Person.class,
41+
Book.class,
42+
Customer.class
43+
};
44+
}
45+
46+
@Override
47+
protected void addConfigOptions(Map options) {
48+
if ( getDialect().getClass().equals( H2Dialect.class ) ) {
49+
options.put(
50+
AvailableSettings.HBM2DDL_IMPORT_FILES,
51+
"schema-generation.sql"
52+
);
53+
options.put( org.hibernate.cfg.AvailableSettings.HBM2DDL_AUTO, "update" );
54+
}
55+
}
56+
57+
@Override
58+
protected String[] getMappings() {
59+
if ( PostgreSQL81Dialect.class.isAssignableFrom( getDialect().getClass() ) ) {
60+
return new String[] { "org/hibernate/userguide/schema/SchemaGenerationTest.hbm.xml" };
61+
}
62+
return super.getMappings();
63+
}
64+
65+
@Test
66+
@RequiresDialect( H2Dialect.class )
67+
public void testH2() {
68+
}
69+
70+
@Test
71+
@RequiresDialect( PostgreSQL81Dialect.class )
72+
public void testPostgres() {
73+
}
74+
75+
//tag::schema-generation-domain-model-example[]
76+
@Entity(name = "Customer")
77+
public class Customer {
78+
79+
@Id
80+
private Integer id;
81+
82+
private String name;
83+
84+
@Basic( fetch = FetchType.LAZY )
85+
private UUID accountsPayableXrefId;
86+
87+
@Lob
88+
@Basic( fetch = FetchType.LAZY )
89+
@LazyGroup( "lobs" )
90+
private Blob image;
91+
92+
public Integer getId() {
93+
return id;
94+
}
95+
96+
public void setId(Integer id) {
97+
this.id = id;
98+
}
99+
100+
public String getName() {
101+
return name;
102+
}
103+
104+
public void setName(String name) {
105+
this.name = name;
106+
}
107+
108+
public UUID getAccountsPayableXrefId() {
109+
return accountsPayableXrefId;
110+
}
111+
112+
public void setAccountsPayableXrefId(UUID accountsPayableXrefId) {
113+
this.accountsPayableXrefId = accountsPayableXrefId;
114+
}
115+
116+
public Blob getImage() {
117+
return image;
118+
}
119+
120+
public void setImage(Blob image) {
121+
this.image = image;
122+
}
123+
}
124+
125+
@Entity(name = "Person")
126+
public static class Person {
127+
128+
@Id
129+
private Long id;
130+
131+
private String name;
132+
133+
@OneToMany(mappedBy = "author")
134+
private List<Book> books = new ArrayList<>( );
135+
136+
public Long getId() {
137+
return id;
138+
}
139+
140+
public void setId(Long id) {
141+
this.id = id;
142+
}
143+
144+
public String getName() {
145+
return name;
146+
}
147+
148+
public void setName(String name) {
149+
this.name = name;
150+
}
151+
152+
public List<Book> getBooks() {
153+
return books;
154+
}
155+
}
156+
157+
@Entity(name = "Book")
158+
public static class Book {
159+
160+
@Id
161+
private Long id;
162+
163+
private String title;
164+
165+
@NaturalId
166+
private String isbn;
167+
168+
@ManyToOne
169+
private Person author;
170+
171+
public Long getId() {
172+
return id;
173+
}
174+
175+
public void setId(Long id) {
176+
this.id = id;
177+
}
178+
179+
public String getTitle() {
180+
return title;
181+
}
182+
183+
public void setTitle(String title) {
184+
this.title = title;
185+
}
186+
187+
public Person getAuthor() {
188+
return author;
189+
}
190+
191+
public void setAuthor(Person author) {
192+
this.author = author;
193+
}
194+
195+
public String getIsbn() {
196+
return isbn;
197+
}
198+
199+
public void setIsbn(String isbn) {
200+
this.isbn = isbn;
201+
}
202+
}
203+
//end::schema-generation-domain-model-example[]
204+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
create sequence book_sequence start with 1 increment by 1

hibernate-core/src/main/java/org/hibernate/annotations/Formula.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
* </pre></blockquote>
2828
*
2929
* <blockquote><pre>
30-
* // call functions
30+
* // call database functions ( e.g. MySQL upper() and substring() )
3131
* &#064;Formula( "upper( substring( middle_name, 1 ) )" )
3232
* Character getMiddleInitial() { ... }
3333
* </pre></blockquote>

0 commit comments

Comments
 (0)