Проблема: у меня есть устаревшее приложение, содержащее один абстрактный суперкласс (скажем, Task
) и более 50 подклассов, называемых SubTask1
, и так далее. Кроме того, у этих подклассов есть различные поля с одинаковыми именами, например filename
, user
et c. Более того, эти подклассы имеют различные отношения @ManyToOne с одним классом (допустим, Property
).
Теперь, как инструмент ORM, мы используем hibernate
со стратегией наследования как JOINED
. Теперь производительность запросов для этих сущностей очень низкая. Следовательно, для повышения производительности я пытаюсь изменить стратегию наследования на SINGLE_TABLE и позволить спящему режиму генерировать схему.
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
abstract public class Task {
public String type;
//Getters and setters
}
@Entity
public class SubTask1 extends Task {
public subTask1Field;
public String user;
public string filename;
@ManyToOne(optional = false)
public Property host;
//Getters and setters
}
@Entity
public class SubTask2 extends Task {
public subTask2Field;
public String user;
public string filename;
@ManyToOne(optional = false)
public Property host;
//Getters and setters
}
@Entity
public class Property {
@Unique
@Required
public String name;
@Required
public String value;
}
Проблема: во время запуска приложения я получаю исключение ниже.
2020-07-09 12:18:26,665 ERROR --- [ main] play : Can't start in PROD mode with errors
javax.persistence.PersistenceException: Unable to build EntityManagerFactory
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:925)
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:900)
at play.db.jpa.JPAPlugin.onApplicationStart(JPAPlugin.java:204)
at play.plugins.PluginCollection.onApplicationStart(PluginCollection.java:616)
at play.Play.start(Play.java:538)
at play.Play.init(Play.java:309)
at play.server.Server.main(Server.java:160)
Caused by: org.hibernate.DuplicateMappingException: Table [Task] contains logical column name [fileName] referenced by multiple physical column names: [`filename`], [`fileName`]
at org.hibernate.cfg.Configuration$MappingsImpl$TableColumnNameBinding.bindLogicalToPhysical(Configuration.java:3021)
at org.hibernate.cfg.Configuration$MappingsImpl$TableColumnNameBinding.addBinding(Configuration.java:3008)
at org.hibernate.cfg.Configuration$MappingsImpl.addColumnBinding(Configuration.java:3053)
at org.hibernate.cfg.Ejb3Column.addColumnBinding(Ejb3Column.java:330)
at org.hibernate.cfg.Ejb3Column.linkWithValue(Ejb3Column.java:322)
at org.hibernate.cfg.annotations.SimpleValueBinder.linkWithValue(SimpleValueBinder.java:361)
at org.hibernate.cfg.annotations.SimpleValueBinder.make(SimpleValueBinder.java:336)
at org.hibernate.cfg.annotations.PropertyBinder.makePropertyAndValue(PropertyBinder.java:193)
at org.hibernate.cfg.annotations.PropertyBinder.makePropertyValueAndBind(PropertyBinder.java:205)
at org.hibernate.cfg.AnnotationBinder.processElementAnnotations(AnnotationBinder.java:2166)
at org.hibernate.cfg.AnnotationBinder.processIdPropertiesIfNotAlready(AnnotationBinder.java:895)
at org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:728)
at org.hibernate.cfg.Configuration$MetadataSourceQueue.processAnnotatedClassesQueue(Configuration.java:3625)
at org.hibernate.cfg.Configuration$MetadataSourceQueue.processMetadata(Configuration.java:3579)
at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1381)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1786)
at org.hibernate.ejb.EntityManagerFactoryImpl.<init>(EntityManagerFactoryImpl.java:96)
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:918)
... 6 common frames omitted
Exception in thread "main" play.exceptions.UnexpectedException: Unexpected Error
at play.Play.start(Play.java:568)
at play.Play.init(Play.java:309)
at play.server.Server.main(Server.java:160)
Caused by: javax.persistence.PersistenceException: Unable to build EntityManagerFactory
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:925)
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:900)
at play.db.jpa.JPAPlugin.onApplicationStart(JPAPlugin.java:204)
at play.plugins.PluginCollection.onApplicationStart(PluginCollection.java:616)
at play.Play.start(Play.java:538)
... 2 more
Caused by: org.hibernate.DuplicateMappingException: Table [Task] contains logical column name [fileName] referenced by multiple physical column names: [`filename`], [`fileName`]
at org.hibernate.cfg.Configuration$MappingsImpl$TableColumnNameBinding.bindLogicalToPhysical(Configuration.java:3021)
at org.hibernate.cfg.Configuration$MappingsImpl$TableColumnNameBinding.addBinding(Configuration.java:3008)
at org.hibernate.cfg.Configuration$MappingsImpl.addColumnBinding(Configuration.java:3053)
at org.hibernate.cfg.Ejb3Column.addColumnBinding(Ejb3Column.java:330)
at org.hibernate.cfg.Ejb3Column.linkWithValue(Ejb3Column.java:322)
at org.hibernate.cfg.annotations.SimpleValueBinder.linkWithValue(SimpleValueBinder.java:361)
at org.hibernate.cfg.annotations.SimpleValueBinder.make(SimpleValueBinder.java:336)
at org.hibernate.cfg.annotations.PropertyBinder.makePropertyAndValue(PropertyBinder.java:193)
at org.hibernate.cfg.annotations.PropertyBinder.makePropertyValueAndBind(PropertyBinder.java:205)
at org.hibernate.cfg.AnnotationBinder.processElementAnnotations(AnnotationBinder.java:2166)
at org.hibernate.cfg.AnnotationBinder.processIdPropertiesIfNotAlready(AnnotationBinder.java:895)
at org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:728)
at org.hibernate.cfg.Configuration$MetadataSourceQueue.processAnnotatedClassesQueue(Configuration.java:3625)
at org.hibernate.cfg.Configuration$MetadataSourceQueue.processMetadata(Configuration.java:3579)
at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1381)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1786)
at org.hibernate.ejb.EntityManagerFactoryImpl.<init>(EntityManagerFactoryImpl.java:96)
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:918)
... 6 more
Вопросы:
- возможно ли преобразовать такую стратегию наследования без внесения изменений в мои классы Entity? Если да, то какие изменения вы предложите по этому поводу?
- Есть ли здесь какой-либо другой способ улучшить производительность запросов? всякий раз, когда я пытаюсь получить объект
Task
, он создает соединение для всех таблиц SubTask
, причем каждая таблица SubTask
объединяется с таблицей Property
.