Hibernate / JPA: checking generated sql before updating DB schema (e.g. .NET EF migration)

So, I'm trying to learn Hibernate / JPA, and I was wondering if there is something like .NET Entity Framework migrations that I can use,

I like the Code First approach (Class → Schema), but automatically generated sql queries can do strange (and dangerous) things in the database. I want to check the generated sql query and then decide if I want to update the database schema.

I have included the show_sql property. I run the project in debug mode to check the generated request and then stop / continue execution.

Is there a more elegant (right?) Way to do what I want?

Edit : also have icctmental schema update function? For example, if I rename a field of my model class, then Hibernate / JPA does the following:

  • If hbm2ddl.auto=create-drop , then it will drop the table and recreate it (data loss).
  • If hbm2ddl.auto=update , then it will add a new colunmn with a new name.

I want to modify an existing table.

0
source share
1 answer

Yes, there is a circuit generator class.

org.hibernate.tool.hbm2ddl.SchemaExport

Here is a sample code on how I use it (note that this was very inspired from the post here)

  package com.mypackage.jpa.util; import java.io.File; import java.net.URL; import java.util.ArrayList; import java.util.List; import org.hibernate.cfg.Configuration; import org.hibernate.tool.hbm2ddl.SchemaExport; public class SchemaGenerator { private Configuration cfg; public static void main(String[] args) throws Exception { File f = new File("."); String directory = f.getAbsoluteFile() + "/src/main/resources/ddl/generated/"; String packageName[] = { "com.mypackage.jpa", "com.mypackage.jpa.legacy", "com.mypackage.jpa.local", "com.mypackage.jpa.local.impl" }; SchemaGenerator gen = new SchemaGenerator(packageName); gen.generate(Dialect.MYSQL, directory); } @SuppressWarnings("rawtypes") public SchemaGenerator(String[] packagesName) throws Exception { cfg = new Configuration(); cfg.setProperty("hibernate.hbm2ddl.auto", "create"); for (String packageName : packagesName) { for (Class clazz : getClasses(packageName)) { cfg.addAnnotatedClass(clazz); } } } @SuppressWarnings("rawtypes") private List<Class> getClasses(String packageName) throws Exception { File directory = null; try { ClassLoader cld = getClassLoader(); URL resource = getResource(packageName, cld); directory = new File(resource.getFile()); } catch (NullPointerException ex) { throw new ClassNotFoundException(packageName + " (" + directory + ") does not appear to be a valid package"); } return collectClasses(packageName, directory); } private ClassLoader getClassLoader() throws ClassNotFoundException { ClassLoader cld = Thread.currentThread().getContextClassLoader(); if (cld == null) { throw new ClassNotFoundException("Can't get class loader."); } return cld; } private URL getResource(String packageName, ClassLoader cld) throws ClassNotFoundException { String path = packageName.replace('.', '/'); URL resource = cld.getResource(path); if (resource == null) { throw new ClassNotFoundException("No resource for " + path); } return resource; } @SuppressWarnings("rawtypes") private List<Class> collectClasses(String packageName, File directory) throws ClassNotFoundException { List<Class> classes = new ArrayList<>(); if (directory.exists()) { String[] files = directory.list(); for (String file : files) { if (file.endsWith(".class")) { // removes the .class extension classes.add(Class.forName(packageName + '.' + file.substring(0, file.length() - 6))); } } } else { throw new ClassNotFoundException(packageName + " is not a valid package"); } return classes; } private void generate(Dialect dialect, String directory) { cfg.setProperty("hibernate.dialect", dialect.getDialectClass()); SchemaExport export = new SchemaExport(cfg); export.setDelimiter(";"); export.setOutputFile(directory + "ddl_" + dialect.name().toLowerCase() + ".sql"); export.setFormat(true); export.execute(true, false, false, false); } private static enum Dialect { ORACLE("org.hibernate.dialect.Oracle10gDialect"), MYSQL("org.hibernate.dialect.MySQLDialect"), HSQL( "org.hibernate.dialect.HSQLDialect"), H2("org.hibernate.dialect.H2Dialect"); private String dialectClass; private Dialect(String dialectClass) { this.dialectClass = dialectClass; } public String getDialectClass() { return dialectClass; } } } 
0
source

Source: https://habr.com/ru/post/1235925/


All Articles