From 7854ffe5b77fe4a6106af81729456ffa19cd1387 Mon Sep 17 00:00:00 2001 From: bbodnar Date: Wed, 27 Dec 2017 22:46:47 +0100 Subject: [PATCH] HHH-12192: include the causing DDL-statement into the message of org.hibernate.tool.schema.spi.CommandAcceptanceException --- .../exec/AbstractScriptTargetOutput.java | 2 +- .../exec/GenerationTargetToDatabase.java | 2 +- ...hemaDatabaseFileGenerationFailureTest.java | 121 ++++++++++++++++++ ...SchemaScriptFileGenerationFailureTest.java | 115 +++++++++++++++++ 4 files changed, 238 insertions(+), 2 deletions(-) create mode 100644 hibernate-core/src/test/java/org/hibernate/jpa/test/schemagen/SchemaDatabaseFileGenerationFailureTest.java create mode 100644 hibernate-core/src/test/java/org/hibernate/jpa/test/schemagen/SchemaScriptFileGenerationFailureTest.java diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/exec/AbstractScriptTargetOutput.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/exec/AbstractScriptTargetOutput.java index 2bb63eee87..4bbc411206 100644 --- a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/exec/AbstractScriptTargetOutput.java +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/exec/AbstractScriptTargetOutput.java @@ -31,7 +31,7 @@ public abstract class AbstractScriptTargetOutput implements ScriptTargetOutput { writer().flush(); } catch (IOException e) { - throw new CommandAcceptanceException( "Could not write to target script file", e ); + throw new CommandAcceptanceException( "Could not write \"" + command + "\" to target script file", e ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/exec/GenerationTargetToDatabase.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/exec/GenerationTargetToDatabase.java index 46f77847ae..90c506e91e 100644 --- a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/exec/GenerationTargetToDatabase.java +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/exec/GenerationTargetToDatabase.java @@ -65,7 +65,7 @@ public class GenerationTargetToDatabase implements GenerationTarget { } catch (SQLException e) { throw new CommandAcceptanceException( - "Error executing DDL via JDBC Statement", + "Error executing \"" + command + "\" via JDBC Statement", e ); } diff --git a/hibernate-core/src/test/java/org/hibernate/jpa/test/schemagen/SchemaDatabaseFileGenerationFailureTest.java b/hibernate-core/src/test/java/org/hibernate/jpa/test/schemagen/SchemaDatabaseFileGenerationFailureTest.java new file mode 100644 index 0000000000..1091330560 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/jpa/test/schemagen/SchemaDatabaseFileGenerationFailureTest.java @@ -0,0 +1,121 @@ +/* + * 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 . + */ +package org.hibernate.jpa.test.schemagen; + +import java.io.IOException; +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Map; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.PersistenceException; +import javax.persistence.Table; + +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.cfg.Environment; +import org.hibernate.jpa.boot.spi.Bootstrap; +import org.hibernate.jpa.boot.spi.EntityManagerFactoryBuilder; +import org.hibernate.jpa.boot.spi.PersistenceUnitDescriptor; +import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; +import org.hibernate.tool.schema.spi.CommandAcceptanceException; +import org.hibernate.tool.schema.spi.SchemaManagementException; + +import org.hibernate.testing.TestForIssue; +import org.junit.Before; +import org.junit.Test; + +import org.mockito.Mockito; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.when; + +/** + * @author Vlad Mihalcea + */ +public class SchemaDatabaseFileGenerationFailureTest { + private Connection connection; + private EntityManagerFactoryBuilder entityManagerFactoryBuilder; + + @Before + public void setUp() throws IOException, SQLException { + connection = Mockito.mock( Connection.class ); + Statement statement = Mockito.mock( Statement.class ); + when( connection.createStatement() ).thenReturn( statement ); + when( statement.execute( anyString() ) ).thenThrow( new SQLException( "Expected" ) ); + + entityManagerFactoryBuilder = Bootstrap.getEntityManagerFactoryBuilder( + buildPersistenceUnitDescriptor(), + getConfig() + ); + } + + @Test + @TestForIssue(jiraKey = "HHH-12192") + public void testGenerateSchemaDoesNotProduceTheSameStatementTwice() throws Exception { + try { + entityManagerFactoryBuilder.generateSchema(); + fail( "Should haave thrown IOException" ); + } + catch (Exception e) { + assertTrue( e instanceof PersistenceException ); + assertTrue( e.getCause() instanceof SchemaManagementException ); + assertTrue( e.getCause().getCause() instanceof CommandAcceptanceException ); + + CommandAcceptanceException commandAcceptanceException = (CommandAcceptanceException) e.getCause() + .getCause(); + + assertTrue( commandAcceptanceException.getMessage().contains( "drop table test_entity if exists" ) ); + + assertTrue( commandAcceptanceException.getCause() instanceof SQLException ); + + SQLException root = (SQLException) e.getCause().getCause().getCause(); + assertEquals( "Expected", root.getMessage() ); + + } + } + + @Entity + @Table(name = "test_entity") + public static class TestEntity { + @Id + private String field; + + private String table; + + public String getField() { + return field; + } + + public void setField(String field) { + this.field = field; + } + } + + private PersistenceUnitDescriptor buildPersistenceUnitDescriptor() { + return new BaseEntityManagerFunctionalTestCase.TestingPersistenceUnitDescriptorImpl( getClass().getSimpleName() ); + } + + private Map getConfig() { + final Map config = Environment.getProperties(); + config.put( AvailableSettings.HBM2DDL_CONNECTION, connection ); + config.put( AvailableSettings.HBM2DDL_DATABASE_ACTION, "drop" ); + config.put( AvailableSettings.HBM2DDL_HALT_ON_ERROR, true ); + ArrayList classes = new ArrayList<>(); + + classes.addAll( Arrays.asList( new Class[] { TestEntity.class } ) ); + config.put( org.hibernate.jpa.AvailableSettings.LOADED_CLASSES, classes ); + return config; + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/jpa/test/schemagen/SchemaScriptFileGenerationFailureTest.java b/hibernate-core/src/test/java/org/hibernate/jpa/test/schemagen/SchemaScriptFileGenerationFailureTest.java new file mode 100644 index 0000000000..a6f81953c3 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/jpa/test/schemagen/SchemaScriptFileGenerationFailureTest.java @@ -0,0 +1,115 @@ +/* + * 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 . + */ +package org.hibernate.jpa.test.schemagen; + +import java.io.IOException; +import java.io.Writer; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Map; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.PersistenceException; +import javax.persistence.Table; + +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.cfg.Environment; +import org.hibernate.jpa.boot.spi.Bootstrap; +import org.hibernate.jpa.boot.spi.EntityManagerFactoryBuilder; +import org.hibernate.jpa.boot.spi.PersistenceUnitDescriptor; +import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; +import org.hibernate.tool.schema.spi.CommandAcceptanceException; +import org.hibernate.tool.schema.spi.SchemaManagementException; + +import org.hibernate.testing.TestForIssue; +import org.junit.Before; +import org.junit.Test; + +import org.mockito.Mockito; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.mockito.Mockito.doThrow; + +/** + * @author Vlad Mihalcea + */ +public class SchemaScriptFileGenerationFailureTest { + private Writer writer; + private EntityManagerFactoryBuilder entityManagerFactoryBuilder; + + @Before + public void setUp() throws IOException { + writer = Mockito.mock( Writer.class ); + doThrow( new IOException( "Expected" ) ).when( writer ).flush(); + + entityManagerFactoryBuilder = Bootstrap.getEntityManagerFactoryBuilder( + buildPersistenceUnitDescriptor(), + getConfig() + ); + } + + @Test + @TestForIssue(jiraKey = "HHH-12192") + public void testGenerateSchemaDoesNotProduceTheSameStatementTwice() throws Exception { + try { + entityManagerFactoryBuilder.generateSchema(); + fail( "Should haave thrown IOException" ); + } + catch (Exception e) { + assertTrue( e instanceof PersistenceException ); + assertTrue( e.getCause() instanceof SchemaManagementException ); + assertTrue( e.getCause().getCause() instanceof CommandAcceptanceException ); + + CommandAcceptanceException commandAcceptanceException = (CommandAcceptanceException) e.getCause() + .getCause(); + + assertTrue( commandAcceptanceException.getMessage().contains( "drop table test_entity if exists" ) ); + + assertTrue( commandAcceptanceException.getCause() instanceof IOException ); + + IOException root = (IOException) e.getCause().getCause().getCause(); + assertEquals( "Expected", root.getMessage() ); + + } + } + + @Entity + @Table(name = "test_entity") + public static class TestEntity { + @Id + private String field; + + private String table; + + public String getField() { + return field; + } + + public void setField(String field) { + this.field = field; + } + } + + private PersistenceUnitDescriptor buildPersistenceUnitDescriptor() { + return new BaseEntityManagerFunctionalTestCase.TestingPersistenceUnitDescriptorImpl( getClass().getSimpleName() ); + } + + private Map getConfig() { + final Map config = Environment.getProperties(); + config.put( org.hibernate.cfg.AvailableSettings.HBM2DDL_SCRIPTS_DROP_TARGET, writer ); + config.put( org.hibernate.cfg.AvailableSettings.HBM2DDL_SCRIPTS_ACTION, "drop-and-create" ); + config.put( AvailableSettings.HBM2DDL_HALT_ON_ERROR, true ); + ArrayList classes = new ArrayList<>(); + + classes.addAll( Arrays.asList( new Class[] { TestEntity.class } ) ); + config.put( org.hibernate.jpa.AvailableSettings.LOADED_CLASSES, classes ); + return config; + } + +}