【问题标题】:How to export database schema using Hibernate SchemaExport with BeanValidation constraints?如何使用带有 BeanValidation 约束的 Hibernate SchemaExport 导出数据库模式?
【发布时间】:2014-06-10 02:59:49
【问题描述】:

请看我的要求:使用 SchemaExport 导出应用了 BeanValidation 约束的数据库模式(例如,@Length(32) 将创建 DB 约束:column(32))。

在 Hibernate 4.1.x 中,我可以在此处使用 hack 代码:https://forum.hibernate.org/viewtopic.php?f=1&t=1024911&view=previous

但上述 hack 代码中所需的 Ejb3Configuration 类已在 Hibernate 4.3.5 中删除。

那么如何在不使用 Ejb3Configuration 的情况下导出应用了 BeanValidation 约束的数据库模式?

【问题讨论】:

    标签: java hibernate bean-validation


    【解决方案1】:

    这样的事情应该可以工作:

    PersistenceUnitDescriptorAdapter pu = new PersistenceUnitDescriptorAdapter() {
        @Override
        public List<String> getManagedClassNames() {
            return Arrays.asList( MyClass.class.getName(), ... );
        }
    };
    
    Map<Object, Object> settings = new HashMap<Object, Object>();
    settings.put( "javax.persistence.schema-generation.scripts.action", "create" );
    settings.put( "javax.persistence.schema-generation.scripts.create-target", "<path-to-export-file>" );
    EntityManagerFactoryBuilderImpl factoryBuilder = new EntityManagerFactoryBuilderImpl( pu, settings );
    factoryBuilder.generateSchema();
    

    它依赖于 Hibernate 内部类,但您之前的解决方案也是如此。你可以在这里创建一个问题 - https://hibernate.onjira.com/browse/HHH - 解释你的用例。也许可以提供使用公共 API 的解决方案。

    【讨论】:

    • 嗨哈迪,我试过你的解决方案,但我发现它只是将 DDL 脚本导出到 SchemaExpoerter。并且 BeanValidation 约束不适用于导出的 DDL 脚本(请参阅detail)。
    【解决方案2】:

    我通过使用 EntityManagerFactoryBuilderImpl 构建的 HibernationConfiguration 找到了一个临时解决方案。它使用 JPA 配置来发出模式脚本(带有 bean-validator 约束)。

    public final class JpaSchemaExporter
    {
        public JpaSchemaExporter(String utilName, String packageName, Properties properties, DialectType dialect,
                     Path outputPath) throws Exception
        {
            this.dialect = dialect;
            this.outputPath = outputPath;
    
            if (Files.exists(outputPath) && !Files.isDirectory(outputPath)) {
                throw new IllegalArgumentException(
                    "Given path already exist and is not a directory! the path:" + outputPath);
            }
            Files.createDirectories(outputPath);
    
            pud = new ParsedPersistenceXmlDescriptor(Resources.getResourceURL("META-INF"));
            pud.setName(utilName);
            pud.addClasses(Resources.getClasseNames(packageName));
            pud.addMappingFiles("META-INF/orm.xml");
            properties.setProperty("hibernate.dialect", dialect.getDialectClass());
    
            ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
            factoryBuilder = new EntityManagerFactoryBuilderImpl( pud, properties );
            factoryBuilder.withValidatorFactory(validatorFactory).build().close(); // create HibernateConfiguration instance
            this.injectBeanValidationConstraintToDdlTranslator();
            validatorFactory.close();
        }
    
        private void injectBeanValidationConstraintToDdlTranslator() {
            try {
                Configuration hibernateConfiguration = factoryBuilder.getHibernateConfiguration();
                ValidatorFactory validatorFactory = (ValidatorFactory) factoryBuilder.getConfigurationValues().get(AvailableSettings.VALIDATION_FACTORY);
                // private class in hibernate
                Method applyRelationalConstraints = Class.forName("org.hibernate.cfg.beanvalidation.TypeSafeActivator")
                    .getMethod("applyRelationalConstraints",
                           ValidatorFactory.class,
                           java.util.Collection.class,
                           Properties.class,
                           Dialect.class);
                applyRelationalConstraints.setAccessible(true);
                Dialect dialectInstance = (Dialect) Class.forName(dialect.getDialectClass()).newInstance();
                applyRelationalConstraints.invoke(null, validatorFactory,
                                  Arrays.asList(Iterators.toArray(hibernateConfiguration.getClassMappings(), PersistentClass.class)) ,
                                  hibernateConfiguration.getProperties(),
                                  dialectInstance);
            }
            catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    
        @SuppressWarnings("unchecked")
        public void create() throws IOException {
            Configuration cfg = factoryBuilder.getHibernateConfiguration();
            cfg.setProperty("hibernate.hbm2ddl.auto", "create");
            SchemaExport export = new SchemaExport(cfg);
            export.setDelimiter(";");
            export.setOutputFile(Paths.get(outputPath.toString(), "ddl_create_" + dialect.name().toLowerCase() + ".sql").toString());
            export.execute(true, false, false, true);
            if (!export.getExceptions().isEmpty()) {
                System.out.println();
                System.out.println("SOME EXCEPTIONS OCCURED WHILE GENERATING THE UPDATE SCRIPT:");
                for (Exception e : (List<Exception>) export.getExceptions()) {
                System.out.println(e.getMessage());
                }
            }
        }
    
        @SuppressWarnings("unchecked")
        public void update() throws IOException {
            Configuration cfg = factoryBuilder.getHibernateConfiguration();
            cfg.setProperty("hibernate.hbm2ddl.auto", "update");
            SchemaUpdate updater = new SchemaUpdate(cfg);
            updater.setDelimiter(";");
            updater.setOutputFile(Paths.get(outputPath.toString(), "ddl_update_" + dialect.name().toLowerCase() + ".sql").toString());
            updater.execute(true, false);
            if (!updater.getExceptions().isEmpty()) {
                System.out.println();
                System.out.println("SOME EXCEPTIONS OCCURED WHILE GENERATING THE UPDATE SCRIPT:");
                for (Exception e : ((List<Exception>) updater.getExceptions())) {
                System.out.println(e.getMessage());
                }
            }
        }
    
        public void validate() {
            Configuration hibernateConfiguration = factoryBuilder.getHibernateConfiguration();
            hibernateConfiguration.setProperty("hibernate.hbm2ddl.auto", "validate");
            SchemaValidator validator = new SchemaValidator(hibernateConfiguration);
            validator.validate();
        }
    
        public static void main(String[] args) throws Exception {
            Properties prop = new Properties(System.getProperties());
            prop.setProperty("hibernate.connection.driver_class", "value in your env");
            prop.setProperty("hibernate.connection.url", "value in your env");
            prop.setProperty("hibernate.connection.username", "value in your env");
            prop.setProperty("hibernate.connection.password", "value in your env");
            Path path = Paths.get("schema output path in your env");
            String packageName = prop.getProperty("package names of jpa classes");
            String unitName = prop.getProperty("jpa Unit Name");
            String[] dialects = "HSQL,MYSQL".split(",");
            for(String dialect : dialects){
                DialectType dialectType = DialectType.valueOf(dialect);
                JpaSchemaExporter ddlExporter = new JpaSchemaExporter(unitName, packageName, prop, dialectType, path);
                ddlExporter.update();
                ddlExporter.create();
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2013-08-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-18
      • 1970-01-01
      • 2010-10-24
      • 2012-04-08
      相关资源
      最近更新 更多