java - 由于@ManyToOne 关系,使用 Hibernate 模式导出器生成模式失败

标签 java spring hibernate jpa

我正在使用 SchemaExporter 生成 ddl 脚本。

public static void main(String[] args) throws Exception {

       SchemaDDLGenerator.execute(Dialect.ORACLE, Key.class);
}

关键类:

@Entity

public class Key extends AbstractEntity {

private static final long serialVersionUID = 7467094398251027638L;

@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
@Column(name = "KEY_SID")
private Long id;
@ManyToOne(cascade = CascadeType.PERSIST, fetch = FetchType.EAGER)
private API granter;
@ManyToOne(cascade = CascadeType.PERSIST, fetch = FetchType.EAGER)
private API grantee;

API 实体类是具有简单列的实体类。

模式生成器:

public class SchemaDDLGenerator {

public static void execute(Dialect dialect, Class<?>... classes) {
    Configuration configuration = new Configuration();
    configuration.setProperty(Environment.DIALECT, dialect.getClassName());
    for (Class<?> entityClass : classes) {
        configuration.addAnnotatedClass(entityClass);
    }
    SchemaExport schemaExport = new SchemaExport(configuration);
    schemaExport.setDelimiter(";");
    boolean consolePrint = true;
    boolean exportInDatabase = false;
    schemaExport.setOutputFile(String.format("ddl_%s_drop.%s ", new Object[] { dialect.name().toLowerCase(), "sql" }));
    schemaExport.drop(false, false);
    schemaExport.setOutputFile(String.format("ddl_%s.%s ", new Object[] { dialect.name().toLowerCase(), "sql" }));
    schemaExport.create(consolePrint, exportInDatabase);
}

它对于其中没有任何关系的实体工作正常,但对于具有@OneToMany 或@ManyToOne 关系的实体会抛出错误。

Exception in thread "main" org.hibernate.AnnotationException: @OneToOne or @ManyToOne on com.example.data.model.ClientRelationship.grantee references an unknown entity: com.example.data.model.Client
at org.hibernate.cfg.ToOneFkSecondPass.doSecondPass(ToOneFkSecondPass.java:109)
at org.hibernate.cfg.Configuration.processEndOfQueue(Configuration.java:1532)
at org.hibernate.cfg.Configuration.processFkSecondPassInOrder(Configuration.java:1453)
at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1358)
at org.hibernate.cfg.Configuration.generateDropSchemaScript(Configuration.java:934)
at org.hibernate.tool.hbm2ddl.SchemaExport.<init>(SchemaExport.java:188)
at org.hibernate.tool.hbm2ddl.SchemaExport.<init>(SchemaExport.java:156)
at com.example.util.db.SchemaDDLGenerator.execute(SchemaDDLGenerator.java:16)
at com.example.data.generator.SchemaGenerator.main(SchemaGenerator.java:67)

以下是基于java的hibernate配置

@Configuration
@Import({ DataConfigDefault.class, DataConfigCi.class })
@ComponentScan(basePackages = "com.example.data.repository.util")
@EnableJpaRepositories(basePackages = { "com.example.data.repository" })
@EnableTransactionManagement(mode = AdviceMode.PROXY)
public class DataConfig {

private static Logger logger = LoggerFactory.getLogger(DataConfig.class);

@Autowired
private Environment environment;

@PostConstruct
public void postConstruct() {
    logger.debug("active profiles: ({})", StringUtils.join(environment.getActiveProfiles(), ","));
}

static DataSource createH2Datasource(String jdbcUrl) {
    logger.debug("creating h2 data source using:  {}", jdbcUrl);
    JdbcDataSource ds = new JdbcDataSource();
    ds.setURL(jdbcUrl);
    ds.setUser("sa");
    ds.setPassword("");
    return ds;
}

@Value("classpath:seed-data.sql")
private Resource h2Schema;

@Value("classpath:test-data.sql")
private Resource h2DataScript;

@Autowired
@Bean
public DataSourceInitializer dataSourceInitializer(final DataSource dataSource) {

    final DataSourceInitializer initializer = new DataSourceInitializer();
    initializer.setDataSource(dataSource);
    initializer.setDatabasePopulator(databasePopulator());
    return initializer;
}

private DatabasePopulator databasePopulator() {
    final ResourceDatabasePopulator populator = new ResourceDatabasePopulator();
    populator.addScript(h2Schema);
    populator.addScript(h2DataScript);
    return populator;
}

@Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
    JpaTransactionManager transactionManager = new JpaTransactionManager();
    transactionManager.setEntityManagerFactory(entityManagerFactory);
    return transactionManager;
}

@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(Environment env, DataSource dataSource) {
    HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
    vendorAdapter.setGenerateDdl(Boolean.TRUE);
    vendorAdapter.setShowSql(Boolean.TRUE);

    LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
    factory.setPersistenceUnitName("merchant");
    factory.setJpaVendorAdapter(vendorAdapter);
    factory.setPackagesToScan("com.example.data.model");
    factory.setDataSource(dataSource);

    factory.setJpaProperties(jpaProperties());
    factory.setLoadTimeWeaver(new InstrumentationLoadTimeWeaver());

    return factory;
}

Properties jpaProperties() {
    Properties props = new Properties();
    props.put("hibernate.query.substitutions", "true 'Y', false 'N'");
    props.put("hibernate.hbm2ddl.auto", "update");
    props.put("hibernate.show_sql", "false");
    props.put("hibernate.format_sql", "true");

    return props;
}

有什么想法吗?

最佳答案

问题是您没有将所有需要的类添加到模式生成器。您可以通过以下方式启用它们:

for (Class<Object> clazz : getClasses(packageName)) {
  cfg.addAnnotatedClass(clazz);
}

private List<Class> getClasses(String packageName) throws ClassNotFoundException {
    List<Class> classes = new ArrayList<>();

    ClassLoader cld = Thread.currentThread().getContextClassLoader();

    String path = packageName.replace('.', '/');
    URL resource = cld.getResource(path);

    File directory = new File(resource.getFile());

    if (!directory.exists()) {
        throw new ClassNotFoundException(packageName + " is not a valid package");
    }
    processDirectory(packageName, classes, directory);

    return classes;
}

关于java - 由于@ManyToOne 关系,使用 Hibernate 模式导出器生成模式失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21125628/

相关文章:

java - 在 WebSphere v7 中重新部署的 EAR 并未反射(reflect)出一些细微的代码更改

java - 启动后如何启动Spring Batch作业?

java - 尝试从父实体java类中删除记录

java - Spring Cloud Dataflow 将缓冲的消息发送到输出 channel

java - 在一种情况下忽略@Formula

java - 忽略关系中的 FetchType.EAGER

java - Android Studio 不生成像 MainActivity 这样的样板 Java 类

java - 计划作业上的 ScheduledExecutorService、timerService 和无状态 EJB

java - 逐个元素地添加数组中的数字

java - 如何为动态创建数据库表的方法编写单元测试?