In my first post on JPA 2.1 Schema generation, I demonstrated how one could use the features built into the JPA 2.1 standard to generate database schemas from your model objects.
One minor annoyance of the schemas generated via this manner (at least by Hibernate), is that they don’t really come out completely usable. Specifically:
- The individual DDL statements are not delimited.
- Each statement is on a single line, which isn’t terribly pretty.
The first problem means that you can’t take the output of the process and run it against your database. Oh, it will work if Hibernate (or another JPA provider) applies it itself to a database, but if you dump the script, save it and expect to use it later, it won’t work unaltered.
The second issue is just a matter of review – it’s harder to double check the generated SQL by eye than if the result was “pretty-printed.”
There is no portable JPA-compliant way of getting around this – the JPA standard is silent on these issues. Fortunately, in the case of Hibernate, it’s pretty straightforward to fix.
Here is the content of ScriptExample3
from the sample code available on GitHub.
public class ScriptExample3 { public static void main(String[] args) { try { Map<String, Object> properties = new HashMap<>(); StringWriter create = new StringWriter(); properties.put("javax.persistence.schema-generation.scripts.action", "create"); properties.put("javax.persistence.schema-generation.scripts.create-target", create); Persistence.generateSchema("script", properties); System.out.println("Create script:"); pretty(create.toString()); System.out.println("Done"); System.exit(0); } catch (Exception e) { e.printStackTrace(); } } private static void pretty(String unformatted) { StringReader lowLevel = new StringReader(unformatted); BufferedReader highLevel = new BufferedReader(lowLevel); DDLFormatterImpl formatter = new DDLFormatterImpl(); highLevel.lines().forEach(x -> { String formatted = formatter.format(x + ";"); System.out.println(formatted); }); } }
As with ScriptExample2
, we capture the output of Persistence.generateSchema
by providing a StringWriter
as the value of the javax.persistence.schema-generation.scripts.create-target
property. (This example shows only the create half of the DDL – the drop half is just as easy.) Now, however, we use a Hibernate-specific class named DDLFormatterImpl
which is capable of formatting DDL statements into “pretty” form. Lines 35-37 take each individual line output by Persistence.generateSchema
, run them through the formatter, append a semi-colon separator and then print them out.
(For those of you who don’t recognize the syntax, this is a Java 8 stream
implementation – the lines()
member of Java 8’s BufferedReader
generates a Stream
of String
s, each of which is then passed to the lambda argument of forEach
. The equivalent non-Stream
implementation would have looked like:
for(;;) { String line = highLevel.readLine(); if (line == null) { break; } String formatted = formatter.format(x + ";"); System.out.println(formatted); }
The two are equivalent – I just happen to be trying to use Java 8 syntax when appropriate.
So there you have it, not only schema generation, but pretty schema generation. The output of this is much easier to read than that from the previous post.
The article JPA 2.1 Schema Generation – Formatted Output originally appeared on the SilverBayTech.com Blog.