/* * Hibernate, Relational Persistence for Idiomatic Java * * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. */ package org.hibernate.test.tool.schema; import java.io.FileInputStream; import java.io.IOException; import java.net.URL; import java.util.HashMap; import java.util.Map; import java.util.Properties; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.PrimaryKeyJoinColumn; import javax.persistence.Table; import org.hibernate.boot.MetadataSources; import org.hibernate.boot.registry.StandardServiceRegistry; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.boot.spi.MetadataImplementor; import org.hibernate.dialect.H2Dialect; import org.hibernate.engine.config.spi.ConfigurationService; import org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.service.spi.ServiceRegistryImplementor; import org.hibernate.tool.schema.internal.DefaultSchemaFilter; import org.hibernate.tool.schema.internal.ExceptionHandlerLoggedImpl; import org.hibernate.tool.schema.internal.HibernateSchemaManagementTool; import org.hibernate.tool.schema.internal.SchemaCreatorImpl; import org.hibernate.tool.schema.internal.SchemaDropperImpl; import org.hibernate.tool.schema.internal.IndividuallySchemaValidatorImpl; import org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase; import org.hibernate.tool.schema.spi.ExceptionHandler; import org.hibernate.tool.schema.spi.ExecutionOptions; import org.hibernate.tool.schema.spi.SchemaManagementException; import org.hibernate.tool.schema.spi.SchemaManagementTool; import org.hibernate.testing.RequiresDialect; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.boot.JdbcConnectionAccessImpl; import org.hibernate.testing.junit4.BaseUnitTestCase; import org.hibernate.testing.logger.LoggerInspectionRule; import org.hibernate.test.util.DdlTransactionIsolatorTestingImpl; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.jboss.logging.Logger; import static org.junit.Assert.assertEquals; /** * @author Dominique Toupin */ @TestForIssue(jiraKey = "HHH-10332") @RequiresDialect(H2Dialect.class) public class IndividuallySchemaValidatorImplTest extends BaseUnitTestCase { @Rule public LoggerInspectionRule logInspection = new LoggerInspectionRule( Logger.getMessageLogger( CoreMessageLogger.class, IndividuallySchemaValidatorImplTest.class.getName() ) ); private StandardServiceRegistry ssr; protected HibernateSchemaManagementTool tool; private Map configurationValues; protected ExecutionOptions executionOptions; @Before public void setUp() throws IOException { ssr = new StandardServiceRegistryBuilder().build(); tool = (HibernateSchemaManagementTool) ssr.getService( SchemaManagementTool.class ); configurationValues = ssr.getService( ConfigurationService.class ).getSettings(); executionOptions = new ExecutionOptions() { @Override public boolean shouldManageNamespaces() { return true; } @Override public Map getConfigurationValues() { return configurationValues; } @Override public ExceptionHandler getExceptionHandler() { return ExceptionHandlerLoggedImpl.INSTANCE; } }; } @After public void tearsDown() { StandardServiceRegistryBuilder.destroy( ssr ); } @Test public void testMissingEntityContainsQualifiedEntityName() throws Exception { final MetadataSources metadataSources = new MetadataSources( ssr ); metadataSources.addAnnotatedClass( MissingEntity.class ); final MetadataImplementor metadata = (MetadataImplementor) metadataSources.buildMetadata(); metadata.validate(); try { getSchemaValidator( metadata ); Assert.fail( "SchemaManagementException expected" ); } catch (SchemaManagementException e) { assertEquals("Schema-validation: missing table [SomeCatalog.SomeSchema.MissingEntity]", e.getMessage()); } } @Test public void testMissingEntityContainsUnqualifiedEntityName() throws Exception { final MetadataSources metadataSources = new MetadataSources( ssr ); metadataSources.addAnnotatedClass( UnqualifiedMissingEntity.class ); final MetadataImplementor metadata = (MetadataImplementor) metadataSources.buildMetadata(); metadata.validate(); try { getSchemaValidator( metadata ); Assert.fail( "SchemaManagementException expected" ); } catch (SchemaManagementException e) { assertEquals("Schema-validation: missing table [UnqualifiedMissingEntity]", e.getMessage()); } } @Test public void testMissingColumn() throws Exception { MetadataSources metadataSources = new MetadataSources( ssr ); metadataSources.addAnnotatedClass( NoNameColumn.class ); MetadataImplementor metadata = (MetadataImplementor) metadataSources.buildMetadata(); metadata.validate(); Map<String, Object> settings = new HashMap<>( ); ServiceRegistryImplementor serviceRegistry = (ServiceRegistryImplementor) new StandardServiceRegistryBuilder() .applySettings( settings ) .build(); DriverManagerConnectionProviderImpl connectionProvider = new DriverManagerConnectionProviderImpl(); connectionProvider.configure( properties() ); final GenerationTargetToDatabase schemaGenerator = new GenerationTargetToDatabase( new DdlTransactionIsolatorTestingImpl( serviceRegistry, new JdbcConnectionAccessImpl( connectionProvider ) ) ); try { new SchemaCreatorImpl( ssr ).doCreation( metadata, serviceRegistry, settings, true, schemaGenerator ); metadataSources = new MetadataSources( ssr ); metadataSources.addAnnotatedClass( NameColumn.class ); metadata = (MetadataImplementor) metadataSources.buildMetadata(); metadata.validate(); try { getSchemaValidator( metadata ); Assert.fail( "SchemaManagementException expected" ); } catch (SchemaManagementException e) { assertEquals("Schema-validation: missing column [name] in table [SomeSchema.ColumnEntity]", e.getMessage()); } } finally { new SchemaDropperImpl( serviceRegistry ).doDrop( metadata, false, schemaGenerator ); serviceRegistry.destroy(); connectionProvider.stop(); } } @Test public void testMismatchColumnType() throws Exception { MetadataSources metadataSources = new MetadataSources( ssr ); metadataSources.addAnnotatedClass( NameColumn.class ); MetadataImplementor metadata = (MetadataImplementor) metadataSources.buildMetadata(); metadata.validate(); Map<String, Object> settings = new HashMap<>( ); ServiceRegistryImplementor serviceRegistry = (ServiceRegistryImplementor) new StandardServiceRegistryBuilder() .applySettings( settings ) .build(); DriverManagerConnectionProviderImpl connectionProvider = new DriverManagerConnectionProviderImpl(); connectionProvider.configure( properties() ); final GenerationTargetToDatabase schemaGenerator = new GenerationTargetToDatabase( new DdlTransactionIsolatorTestingImpl( serviceRegistry, new JdbcConnectionAccessImpl( connectionProvider ) ) ); try { new SchemaCreatorImpl( ssr ).doCreation( metadata, serviceRegistry, settings, true, schemaGenerator ); metadataSources = new MetadataSources( ssr ); metadataSources.addAnnotatedClass( IntegerNameColumn.class ); metadata = (MetadataImplementor) metadataSources.buildMetadata(); metadata.validate(); try { getSchemaValidator( metadata ); Assert.fail( "SchemaManagementException expected" ); } catch (SchemaManagementException e) { assertEquals("Schema-validation: wrong column type encountered in column [name] in table [SomeSchema.ColumnEntity]; found [varchar (Types#VARCHAR)], but expecting [integer (Types#INTEGER)]", e.getMessage()); } } finally { new SchemaDropperImpl( serviceRegistry ).doDrop( metadata, false, schemaGenerator ); serviceRegistry.destroy(); connectionProvider.stop(); } } protected void getSchemaValidator(MetadataImplementor metadata) { new IndividuallySchemaValidatorImpl( tool, DefaultSchemaFilter.INSTANCE ) .doValidation( metadata, executionOptions ); } protected Properties properties() { Properties properties = new Properties( ); URL propertiesURL = Thread.currentThread().getContextClassLoader().getResource( "hibernate.properties" ); try(FileInputStream inputStream = new FileInputStream( propertiesURL.getFile() )) { properties.load( inputStream ); } catch (IOException e) { throw new IllegalArgumentException( e ); } return properties; } @Entity @PrimaryKeyJoinColumn @Table(name = "UnqualifiedMissingEntity") public static class UnqualifiedMissingEntity { private String id; @Id public String getId() { return id; } public void setId(String id) { this.id = id; } } @Entity @PrimaryKeyJoinColumn @Table(name = "MissingEntity", catalog = "SomeCatalog", schema = "SomeSchema") public static class MissingEntity { private String id; @Id public String getId() { return id; } public void setId(String id) { this.id = id; } } @Entity @PrimaryKeyJoinColumn @Table(name = "ColumnEntity", schema = "SomeSchema") public static class NoNameColumn { private String id; @Id public String getId() { return id; } public void setId(String id) { this.id = id; } } @Entity @PrimaryKeyJoinColumn @Table(name = "ColumnEntity", schema = "SomeSchema") public static class NameColumn { private String id; private String name; @Id public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } } @Entity @PrimaryKeyJoinColumn @Table(name = "ColumnEntity", schema = "SomeSchema") public static class IntegerNameColumn { private String id; private Integer name; @Id public String getId() { return id; } public void setId(String id) { this.id = id; } public Integer getName() { return name; } public void setName(Integer name) { this.name = name; } } }