HHH-16578 - Add a test that shows the more restrictive schema validation (less dependant on columnDefinition info, and more on the use of @JdbcTypeCode)
Signed-off-by: Jan Schatteman <jschatte@redhat.com>
This commit is contained in:
parent
be9692765c
commit
fe958f9c12
|
@ -0,0 +1,266 @@
|
|||
/*
|
||||
* 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.orm.test.tool.schema;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.sql.Types;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.annotations.JdbcTypeCode;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.dialect.MySQLDialect;
|
||||
import org.hibernate.engine.config.spi.ConfigurationService;
|
||||
import org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl;
|
||||
import org.hibernate.internal.util.PropertiesHelper;
|
||||
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.IndividuallySchemaValidatorImpl;
|
||||
import org.hibernate.tool.schema.spi.ContributableMatcher;
|
||||
import org.hibernate.tool.schema.spi.ExceptionHandler;
|
||||
import org.hibernate.tool.schema.spi.ExecutionOptions;
|
||||
import org.hibernate.tool.schema.spi.SchemaFilter;
|
||||
import org.hibernate.tool.schema.spi.SchemaManagementException;
|
||||
import org.hibernate.tool.schema.spi.SchemaManagementTool;
|
||||
import org.hibernate.tool.schema.spi.SchemaValidator;
|
||||
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.JiraKey;
|
||||
import org.hibernate.testing.orm.junit.RequiresDialect;
|
||||
import org.hibernate.testing.orm.junit.ServiceRegistry;
|
||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||
import org.hibernate.testing.orm.junit.Setting;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Table;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
/**
|
||||
* @author Jan Schatteman
|
||||
*/
|
||||
@ServiceRegistry(
|
||||
settings = {
|
||||
@Setting( name = AvailableSettings.HBM2DDL_AUTO, value = "none" )
|
||||
}
|
||||
)
|
||||
@DomainModel(
|
||||
annotatedClasses = {
|
||||
MySQLColumnValidationTest.TestEntity1.class,
|
||||
MySQLColumnValidationTest.TestEntity2.class,
|
||||
MySQLColumnValidationTest.TestEntity3.class
|
||||
}
|
||||
)
|
||||
@SessionFactory( exportSchema = false )
|
||||
@JiraKey( value = "HHH-16578" )
|
||||
@RequiresDialect( value = MySQLDialect.class )
|
||||
public class MySQLColumnValidationTest {
|
||||
|
||||
private DriverManagerConnectionProviderImpl connectionProvider;
|
||||
|
||||
@BeforeAll
|
||||
public void init() {
|
||||
connectionProvider = new DriverManagerConnectionProviderImpl();
|
||||
connectionProvider.configure( PropertiesHelper.map( Environment.getProperties() ) );
|
||||
|
||||
try( Connection connection = connectionProvider.getConnection();
|
||||
Statement statement = connection.createStatement() ) {
|
||||
|
||||
try {
|
||||
statement.execute( "DROP TABLE TEST_DATA1" );
|
||||
statement.execute( "DROP TABLE TEST_DATA2" );
|
||||
statement.execute( "DROP TABLE TEST_DATA3" );
|
||||
}
|
||||
catch (SQLException e) {
|
||||
}
|
||||
|
||||
statement.execute( "CREATE TABLE `TEST_DATA1` ( " +
|
||||
" `ID` int unsigned NOT NULL, " +
|
||||
" `INTEGRAL1` tinyint unsigned DEFAULT '0', " +
|
||||
" `INTEGRAL2` tinyint unsigned DEFAULT '0', " +
|
||||
" PRIMARY KEY (`ID`)" +
|
||||
") ENGINE=InnoDB" );
|
||||
|
||||
statement.execute( "CREATE TABLE `TEST_DATA2` ( " +
|
||||
" `ID` int unsigned NOT NULL, " +
|
||||
" `INTEGRAL1` tinyint unsigned DEFAULT '0', " +
|
||||
" PRIMARY KEY (`ID`)" +
|
||||
") ENGINE=InnoDB" );
|
||||
|
||||
statement.execute( "CREATE TABLE `TEST_DATA3` ( " +
|
||||
" `ID` int unsigned NOT NULL, " +
|
||||
" `INTEGRAL1` tinyint unsigned DEFAULT '0', " +
|
||||
" PRIMARY KEY (`ID`)" +
|
||||
") ENGINE=InnoDB" );
|
||||
|
||||
}
|
||||
catch (SQLException e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
public void releaseResources() {
|
||||
try( Connection connection = connectionProvider.getConnection();
|
||||
Statement statement = connection.createStatement() ) {
|
||||
try {
|
||||
statement.execute( "DROP TABLE TEST_DATA1" );
|
||||
statement.execute( "DROP TABLE TEST_DATA2" );
|
||||
statement.execute( "DROP TABLE TEST_DATA3" );
|
||||
}
|
||||
catch (SQLException e) {
|
||||
}
|
||||
}
|
||||
catch (SQLException e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
|
||||
connectionProvider.stop();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateColumn(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
TestEntity1 te1 = new TestEntity1( 1, 1, 2 );
|
||||
session.persist( te1 );
|
||||
}
|
||||
);
|
||||
|
||||
ConfigurationService configurationService = scope.getSessionFactory().getServiceRegistry().getService(
|
||||
ConfigurationService.class );
|
||||
ExecutionOptions executionOptions = new ExecutionOptions() {
|
||||
@Override
|
||||
public boolean shouldManageNamespaces() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map getConfigurationValues() {
|
||||
return configurationService.getSettings();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExceptionHandler getExceptionHandler() {
|
||||
return ExceptionHandlerLoggedImpl.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SchemaFilter getSchemaFilter() {
|
||||
return SchemaFilter.ALL;
|
||||
}
|
||||
};
|
||||
|
||||
HibernateSchemaManagementTool hsmt = (HibernateSchemaManagementTool) scope.getSessionFactory()
|
||||
.getServiceRegistry()
|
||||
.getService( SchemaManagementTool.class );
|
||||
SchemaValidator schemaValidator = new IndividuallySchemaValidatorImpl( hsmt, DefaultSchemaFilter.INSTANCE );
|
||||
|
||||
try {
|
||||
schemaValidator.doValidation( scope.getMetadataImplementor(), executionOptions,
|
||||
contributed -> {
|
||||
return "test_data1".equalsIgnoreCase( contributed.getExportIdentifier() );
|
||||
} );
|
||||
}
|
||||
catch (SchemaManagementException e) {
|
||||
fail( e.getMessage() );
|
||||
}
|
||||
|
||||
try {
|
||||
schemaValidator.doValidation( scope.getMetadataImplementor(), executionOptions,
|
||||
contributed -> {
|
||||
return "test_data2".equalsIgnoreCase( contributed.getExportIdentifier() );
|
||||
} );
|
||||
fail( "SchemaManagementException expected" );
|
||||
}
|
||||
catch (SchemaManagementException e) {
|
||||
assertEquals(
|
||||
"Schema-validation: wrong column type encountered in column [integral1] in table [TEST_DATA2]; found [tinyint unsigned (Types#TINYINT)], but expecting [tinyint (Types#INTEGER)]",
|
||||
e.getMessage()
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
schemaValidator.doValidation( scope.getMetadataImplementor(), executionOptions,
|
||||
contributed -> {
|
||||
return "test_data3".equalsIgnoreCase( contributed.getExportIdentifier() );
|
||||
} );
|
||||
fail( "SchemaManagementException expected" );
|
||||
}
|
||||
catch (SchemaManagementException e) {
|
||||
assertEquals(
|
||||
"Schema-validation: wrong column type encountered in column [integral1] in table [TEST_DATA3]; found [tinyint unsigned (Types#TINYINT)], but expecting [tinyint unsigned default '0' (Types#INTEGER)]",
|
||||
e.getMessage()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "test_entity1")
|
||||
@Table(name = "TEST_DATA1")
|
||||
public static class TestEntity1 {
|
||||
@Id
|
||||
@Column(name = "id", columnDefinition = "INT(10) UNSIGNED NOT NULL")
|
||||
private Integer id;
|
||||
|
||||
@JdbcTypeCode( Types.TINYINT )
|
||||
@Column(name = "integral1", columnDefinition = "tinyint")
|
||||
private int integral1;
|
||||
|
||||
@JdbcTypeCode( Types.TINYINT )
|
||||
@Column(name = "integral2", columnDefinition = "tinyint UNSIGNED DEFAULT '0'")
|
||||
private int integral2;
|
||||
|
||||
public TestEntity1( Integer id, int integral1, int integral2 ) {
|
||||
this.id = id;
|
||||
this.integral1 = integral1;
|
||||
this.integral2 = integral2;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "test_entity2")
|
||||
@Table(name = "TEST_DATA2")
|
||||
public static class TestEntity2 {
|
||||
@Id
|
||||
@Column(name = "id", columnDefinition = "INT(10) UNSIGNED NOT NULL")
|
||||
private Integer id;
|
||||
|
||||
@Column(name = "integral1", columnDefinition = "tinyint")
|
||||
private int integral1;
|
||||
|
||||
public TestEntity2( Integer id, int integral1 ) {
|
||||
this.id = id;
|
||||
this.integral1 = integral1;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "test_entity3")
|
||||
@Table(name = "TEST_DATA3")
|
||||
public static class TestEntity3 {
|
||||
@Id
|
||||
@Column(name = "id", columnDefinition = "INT(10) UNSIGNED NOT NULL")
|
||||
private Integer id;
|
||||
|
||||
@Column(name = "integral1", columnDefinition = "tinyint UNSIGNED DEFAULT '0'")
|
||||
private int integral1;
|
||||
|
||||
public TestEntity3( Integer id, int integral1 ) {
|
||||
this.id = id;
|
||||
this.integral1 = integral1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue