You may find the following hack useful:
Code:
/**
* Uses the JPA configuration to emit the schema creation script.
*/
/*
* The deprecation can not be avoided, as it appears that Ejb3Configuration was
* deprecated before its substitute has been implemented (the JIRA issues
* referenced by the deprecation notice have been rescheduled for Hibernate 5).
* Also, as of hibernate 4.1.2, hibernate still uses Ejb3Configuration to create
* an EntityManagerFactory.
*/
@SuppressWarnings("deprecation")
public class ExportSchema {
private static final String persistenceUnitName = "main";
public static final String outputFileName = "target/populate_schema.sql";
/**
* @param dialectClass the dialect to be used by the sql script
*/
public static void export(Class<? extends Dialect> dialectClass) {
new File(outputFileName).getParentFile().mkdirs();
Ejb3Configuration cfg = new Ejb3Configuration();
if (beanValidationInClasspath()) {
injectBeanValidationConstraintToDdlTranslator(cfg, dialectClass);
}
cfg.configure(persistenceUnitName, null);
cfg.setProperty("hibernate.dialect", dialectClass.getName());
SchemaExport exporter = new SchemaExport(cfg.getHibernateConfiguration());
exporter.setFormat(true);
exporter.setDelimiter(";");
exporter.setOutputFile(outputFileName);
exporter.execute(true, false, false, true);
}
private static boolean beanValidationInClasspath() {
try {
Class.forName("javax.validation.constraints.NotNull");
return true;
} catch (ClassNotFoundException e) {
return false;
}
}
// This integration is usually performed by BeanValidationIntegrator.
// Unfortunately, that integration will only be activated upon
// initialization of the ServiceRegistry, which initializes
// DatasourceConnectionProviderImpl, which looks up the datasource,
// which requires a JNDI context ...
// We therefore reimplement the relevant parts of BeanValidatorIntegrator.
// Since that must occur after secondPassCompile(), which is invoked by
// Configuration.generateSchemaCreationScript, which is invoked by
// SchemaExport, some fancy subclassing is needed to invoke the integration
// at the right time.
private static void injectBeanValidationConstraintToDdlTranslator(Ejb3Configuration jpaCfg, final Class<? extends Dialect> dialectClass) {
try {
Field cfgField = Ejb3Configuration.class.getDeclaredField("cfg");
cfgField.setAccessible(true);
cfgField.set(jpaCfg, new Configuration() {
@Override
protected void secondPassCompile() throws MappingException {
super.secondPassCompile();
try {
// thank you, hibernate folks, for making this useful class package private ...
Method applyDDL = Class.forName("org.hibernate.cfg.beanvalidation.TypeSafeActivator") //
.getMethod("applyDDL", Collection.class, Properties.class, Dialect.class);
applyDDL.setAccessible(true);
applyDDL.invoke(null, classes.values(), getProperties(), dialectClass.newInstance());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
});
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
It causes bean validation constraints to be propagated to DDL when using hibernate-core-4.1.4.Final. A database connection is not required.