Я пытаюсь изучить JPA, поэтому я создал простой JavaSE-JPA проект (без Spring).Я хотел, чтобы таблицы БД создавались при запуске приложения с помощью моих сопоставлений аннотаций.И я смог достичь этого.
Затем я решил сделать некоторые таблицы уже существующими и доступными только для чтения, в то время как другие будут создаваться при запуске.Но не смог этого сделать.
Я сделал следующее.
- Сделал некоторые из моих сущностей неизменными.
- Вручную создавать и заполнять таблицы в БД для этих неизменяемых объектов.
- Создал 2 постоянных модуля и использовал «validate» для readOnlyPU и «create» для основного PU в свойствах гибернации.
Не сработало.Таблицы удалялись и создавались заново при запуске.Я думаю, потому что один из моих постоянных юнитов создал, и я не смог найти, чтобы сообщить этому PU о том, какую сущность игнорировать при создании.
Я не хочу упоминатьклассы или имя пакета в XML под постоянным модулем.Может быть, это будет работать, но не элегантное решение
Итак
- Я создал другую схему в БД и поместил свои таблицы только для чтения и данные в эту новую схему.
- Обновлен мой постоянный модуль readOnly с этой схемой.
- Упоминается соответствующий атрибут схемы во всех изменяемых и неизменяемых аннотациях JPA @table.
Но при запуске приложения проверка гибернации не выполняется.Ниже приведен соответствующий фрагмент кода.
@Entity
@Table(name = "CONTINENTS",schema = "readOnlySchema")
public class Continent {
@Id
private int id;
private String continentName;
private String continent;
private Continent() {}
.........
............
}
@Entity
@Table(name = "COUNTRIES",schema = "readOnlySchema")
public class Country {
@Id
private int id;
private String countryCode;
private String countryName;
private String currencyCode;
private String capital;
@ManyToOne
private Continent continent;
...........
............
private Country() {}
}
@Entity
@Table(name = "ADDRESS", schema = "schema1")
public class Address {
@Id
@GeneratedValue
private long id;
...........
............
@ManyToOne
private Country country;
}
<persistence-unit name="pu">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<properties>
<property name="javax.persistence.jdbc.driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/schema1?serverTimezone=EST"/>
<property name="javax.persistence.jdbc.user" value="....."/>
<property name="javax.persistence.jdbc.password" value="....."/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.hbm2ddl.auto" value="create"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect" />
</properties>
</persistence-unit>
<persistence-unit name="ReadOnlyPU">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<properties>
<property name="javax.persistence.jdbc.driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/readOnlySchema?serverTimezone=EST"/>
<property name="javax.persistence.jdbc.user" value="...."/>
<property name="javax.persistence.jdbc.password" value="...."/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.hbm2ddl.auto" value="validate"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect" />
</properties>
</persistence-unit>
Все таблицы создаются в моей основной схеме схемы1, и ниже выдается исключение.
Program started
Jul 01, 2019 10:07:47 AM org.hibernate.jpa.internal.util.LogHelper logPersistenceUnitInformation
INFO: HHH000204: Processing PersistenceUnitInfo [
name: pu
...]
Jul 01, 2019 10:07:48 AM org.hibernate.Version logVersion
INFO: HHH000412: Hibernate Core {5.3.10.Final}
Jul 01, 2019 10:07:48 AM org.hibernate.cfg.Environment <clinit>
INFO: HHH000206: hibernate.properties not found
Jul 01, 2019 10:07:48 AM org.hibernate.annotations.common.reflection.java.JavaReflectionManager <clinit>
INFO: HCANN000001: Hibernate Commons Annotations {5.0.4.Final}
Jul 01, 2019 10:07:48 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
WARN: HHH10001002: Using Hibernate built-in connection pool (not for production use!)
Jul 01, 2019 10:07:48 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001005: using driver [com.mysql.cj.jdbc.Driver] at URL [jdbc:mysql://localhost:3306/schema1?serverTimezone=EST]
Jul 01, 2019 10:07:48 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001001: Connection properties: {user=mps, password=****}
Jul 01, 2019 10:07:48 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001003: Autocommit mode: false
Jul 01, 2019 10:07:48 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl$PooledConnections <init>
INFO: HHH000115: Hibernate connection pool size: 20 (min=1)
Jul 01, 2019 10:07:49 AM org.hibernate.dialect.Dialect <init>
INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQL5InnoDBDialect
Hibernate: alter table COUNTRIES drop foreign key FK4hiubsv31sjivffus7ohgj9ws
Jul 01, 2019 10:07:50 AM org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl getIsolatedConnection
INFO: HHH10001501: Connection obtained from JdbcConnectionAccess [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess@4a31c2ee] for (non-JTA) DDL execution was not in auto-commit mode; the Connection 'local transaction' will be committed and the Connection will be set into auto-commit mode.
Jul 01, 2019 10:07:50 AM org.hibernate.tool.schema.internal.ExceptionHandlerLoggedImpl handleException
WARN: GenerationTarget encountered exception accepting command : Error executing DDL "alter table COUNTRIES drop foreign key FK4hiubsv31sjivffus7ohgj9ws" via JDBC Statement
org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL "alter table COUNTRIES drop foreign key FK4hiubsv31sjivffus7ohgj9ws" via JDBC Statement
at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept(GenerationTargetToDatabase.java:67)
at org.hibernate.tool.schema.internal.SchemaDropperImpl.applySqlString(SchemaDropperImpl.java:375)
at org.hibernate.tool.schema.internal.SchemaDropperImpl.applySqlStrings(SchemaDropperImpl.java:359)
at org.hibernate.tool.schema.internal.SchemaDropperImpl.applyConstraintDropping(SchemaDropperImpl.java:331)
at org.hibernate.tool.schema.internal.SchemaDropperImpl.dropFromMetadata(SchemaDropperImpl.java:230)
at org.hibernate.tool.schema.internal.SchemaDropperImpl.performDrop(SchemaDropperImpl.java:154)
at org.hibernate.tool.schema.internal.SchemaDropperImpl.doDrop(SchemaDropperImpl.java:126)
at org.hibernate.tool.schema.internal.SchemaDropperImpl.doDrop(SchemaDropperImpl.java:112)
at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.performDatabaseAction(SchemaManagementToolCoordinator.java:144)
at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.process(SchemaManagementToolCoordinator.java:72)
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:310)
at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:467)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:939)
at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory(HibernatePersistenceProvider.java:56)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:79)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:54)
at com.mps.jpa.PersistenceManager$SingletonClassHolder.<clinit>(PersistenceManager.java:18)
at com.mps.jpa.PersistenceManager.getEntityManagerFactory(PersistenceManager.java:24)
at com.mps.jpa.PersistenceManager.getEntityManager(PersistenceManager.java:27)
at com.mps.jpa.App.main(App.java:21)
Caused by: java.sql.SQLSyntaxErrorException: Table 'schema1.countries' doesn't exist
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:120)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97)
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)
at com.mysql.cj.jdbc.StatementImpl.executeInternal(StatementImpl.java:782)
at com.mysql.cj.jdbc.StatementImpl.execute(StatementImpl.java:666)
at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept(GenerationTargetToDatabase.java:54)
... 19 more
Hibernate: drop table if exists CONTINENTS
Hibernate: drop table if exists COUNTRIES
Hibernate: alter table ADDRESS drop foreign key FK1prteh5rw6mdmeh06djuevhg4
Jul 01, 2019 10:07:50 AM org.hibernate.tool.schema.internal.ExceptionHandlerLoggedImpl handleException
WARN: GenerationTarget encountered exception accepting command : Error executing DDL "alter table ADDRESS drop foreign key FK1prteh5rw6mdmeh06djuevhg4" via JDBC Statement
org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL "alter table ADDRESS drop foreign key FK1prteh5rw6mdmeh06djuevhg4" via JDBC Statement
at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept(GenerationTargetToDatabase.java:67)
at org.hibernate.tool.schema.internal.SchemaDropperImpl.applySqlString(SchemaDropperImpl.java:375)
at org.hibernate.tool.schema.internal.SchemaDropperImpl.applySqlStrings(SchemaDropperImpl.java:359)
at org.hibernate.tool.schema.internal.SchemaDropperImpl.applyConstraintDropping(SchemaDropperImpl.java:331)
at org.hibernate.tool.schema.internal.SchemaDropperImpl.dropFromMetadata(SchemaDropperImpl.java:230)
at org.hibernate.tool.schema.internal.SchemaDropperImpl.performDrop(SchemaDropperImpl.java:154)
at org.hibernate.tool.schema.internal.SchemaDropperImpl.doDrop(SchemaDropperImpl.java:126)
at org.hibernate.tool.schema.internal.SchemaDropperImpl.doDrop(SchemaDropperImpl.java:112)
at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.performDatabaseAction(SchemaManagementToolCoordinator.java:144)
at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.process(SchemaManagementToolCoordinator.java:72)
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:310)
at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:467)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:939)
at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory(HibernatePersistenceProvider.java:56)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:79)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:54)
at com.mps.jpa.PersistenceManager$SingletonClassHolder.<clinit>(PersistenceManager.java:18)
at com.mps.jpa.PersistenceManager.getEntityManagerFactory(PersistenceManager.java:24)
at com.mps.jpa.PersistenceManager.getEntityManager(PersistenceManager.java:27)
at com.mps.jpa.App.main(App.java:21)
Caused by: java.sql.SQLSyntaxErrorException: Table 'schema1.address' doesn't exist
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:120)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97)
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)
at com.mysql.cj.jdbc.StatementImpl.executeInternal(StatementImpl.java:782)
at com.mysql.cj.jdbc.StatementImpl.execute(StatementImpl.java:666)
at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept(GenerationTargetToDatabase.java:54)
... 19 more
Hibernate: drop table if exists ADDRESS
Hibernate: drop table if exists hibernate_sequence
Hibernate: create table CONTINENTS (id integer not null, continent varchar(255), continentName varchar(255), primary key (id)) engine=InnoDB
Jul 01, 2019 10:07:50 AM org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl getIsolatedConnection
INFO: HHH10001501: Connection obtained from JdbcConnectionAccess [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess@2e1792e7] for (non-JTA) DDL execution was not in auto-commit mode; the Connection 'local transaction' will be committed and the Connection will be set into auto-commit mode.
Hibernate: create table COUNTRIES (id integer not null, capital varchar(255), countryCode varchar(255), countryName varchar(255), currencyCode varchar(255), continent_id integer, primary key (id)) engine=InnoDB
Hibernate: create table ADDRESS (id bigint not null, addressLine1 varchar(255), city varchar(255), state varchar(255), street varchar(255), zip varchar(255), country_id integer, primary key (id)) engine=InnoDB
Hibernate: create table hibernate_sequence (next_val bigint) engine=InnoDB
Hibernate: insert into hibernate_sequence values ( 1 )
Hibernate: alter table COUNTRIES add constraint FK4hiubsv31sjivffus7ohgj9ws foreign key (continent_id) references CONTINENTS (id)
Hibernate: alter table ADDRESS add constraint FK1prteh5rw6mdmeh06djuevhg4 foreign key (country_id) references COUNTRIES (id)
Jul 01, 2019 10:07:50 AM org.hibernate.tool.schema.internal.SchemaCreatorImpl applyImportSources
INFO: HHH000476: Executing import script 'org.hibernate.tool.schema.internal.exec.ScriptSourceInputNonExistentImpl@796d3c9f'
Jul 01, 2019 10:07:50 AM org.hibernate.hql.internal.QueryTranslatorFactoryInitiator initiateService
INFO: HHH000397: Using ASTQueryTranslatorFactory
Jul 01, 2019 10:07:50 AM org.hibernate.jpa.internal.util.LogHelper logPersistenceUnitInformation
INFO: HHH000204: Processing PersistenceUnitInfo [
name: ReadOnlyPU
...]
Jul 01, 2019 10:07:50 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
WARN: HHH10001002: Using Hibernate built-in connection pool (not for production use!)
Jul 01, 2019 10:07:50 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001005: using driver [com.mysql.cj.jdbc.Driver] at URL [jdbc:mysql://localhost:3306/readOnlySchema?serverTimezone=EST]
Jul 01, 2019 10:07:50 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001001: Connection properties: {user=mps, password=****}
Jul 01, 2019 10:07:50 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001003: Autocommit mode: false
Jul 01, 2019 10:07:50 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl$PooledConnections <init>
INFO: HHH000115: Hibernate connection pool size: 20 (min=1)
Jul 01, 2019 10:07:50 AM org.hibernate.dialect.Dialect <init>
INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQL5InnoDBDialect
Jul 01, 2019 10:07:50 AM org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl getIsolatedConnection
INFO: HHH10001501: Connection obtained from JdbcConnectionAccess [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess@66e889df] for (non-JTA) DDL execution was not in auto-commit mode; the Connection 'local transaction' will be committed and the Connection will be set into auto-commit mode.
Jul 01, 2019 10:07:50 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl stop
INFO: HHH10001008: Cleaning up connection pool [jdbc:mysql://localhost:3306/readOnlySchema?serverTimezone=EST]
Exception in thread "main" java.lang.ExceptionInInitializerError
at com.mps.jpa.PersistenceManager.getEntityManagerFactory(PersistenceManager.java:24)
at com.mps.jpa.PersistenceManager.getEntityManager(PersistenceManager.java:27)
at com.mps.jpa.App.main(App.java:21)
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: ReadOnlyPU] Unable to build Hibernate SessionFactory
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.persistenceException(EntityManagerFactoryBuilderImpl.java:1016)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:942)
at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory(HibernatePersistenceProvider.java:56)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:79)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:54)
at com.mps.jpa.PersistenceManager$SingletonClassHolder.<clinit>(PersistenceManager.java:19)
... 3 more
Caused by: org.hibernate.tool.schema.spi.SchemaManagementException: Schema-validation: missing table [schema1.ADDRESS]
at org.hibernate.tool.schema.internal.AbstractSchemaValidator.validateTable(AbstractSchemaValidator.java:121)
at org.hibernate.tool.schema.internal.GroupedSchemaValidatorImpl.validateTables(GroupedSchemaValidatorImpl.java:42)
at org.hibernate.tool.schema.internal.AbstractSchemaValidator.performValidation(AbstractSchemaValidator.java:89)
at org.hibernate.tool.schema.internal.AbstractSchemaValidator.doValidation(AbstractSchemaValidator.java:68)
at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.performDatabaseAction(SchemaManagementToolCoordinator.java:191)
at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.process(SchemaManagementToolCoordinator.java:72)
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:310)
at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:467)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:939)
... 7 more