HHH-10515 - Add test for issue

HHH-10515 - Fix Stored procedure execution fails to find column

HHH-10515 : Add test case using no JDBC DatabaseMetaData; move original test case to hibernate-core

HHH-10515 - Fix Stored procedure execution fails to find column
This commit is contained in:
Andrea Boriero 2016-02-11 13:47:07 +00:00 committed by Gail Badner
parent dde7a5d1a5
commit 0eaf431ef6
6 changed files with 255 additions and 2 deletions

View File

@ -2804,4 +2804,15 @@ public abstract class Dialect implements ConversionContext {
public boolean supportsPartitionBy() {
return false;
}
/**
* Override the DatabaseMetaData#supportsNamedParameters()
*
* @return boolean
*
* @throws SQLException Accessing the DatabaseMetaData can throw it. Just re-throw and Hibernate will handle.
*/
public boolean supportsNamedParameters(DatabaseMetaData databaseMetaData) throws SQLException {
return databaseMetaData != null && databaseMetaData.supportsNamedParameters();
}
}

View File

@ -51,6 +51,7 @@ import org.hibernate.persister.entity.Lockable;
import org.hibernate.type.StandardBasicTypes;
import org.jboss.logging.Logger;
import java.sql.DatabaseMetaData;
/**
* An SQL dialect compatible with HSQLDB (HyperSQL).
@ -669,4 +670,9 @@ public class HSQLDialect extends Dialect {
public NameQualifierSupport getNameQualifierSupport() {
return NameQualifierSupport.SCHEMA;
}
@Override
public boolean supportsNamedParameters(DatabaseMetaData databaseMetaData) throws SQLException {
return false;
}
}

View File

@ -192,7 +192,6 @@ public class ExtractedDatabaseMetaDataImpl implements ExtractedDatabaseMetaData
lobLocatorUpdateCopy = databaseMetaData.locatorsUpdateCopy();
typeInfoSet = new LinkedHashSet<TypeInfo>();
typeInfoSet.addAll( TypeInfo.extractTypeInfo( databaseMetaData ) );
return this;
}

View File

@ -75,7 +75,6 @@ public class JdbcEnvironmentImpl implements JdbcEnvironment {
this.nameQualifierSupport = nameQualifierSupport;
this.sqlExceptionHelper = buildSqlExceptionHelper( dialect, logWarnings( cfgService, dialect ) );
this.extractedMetaDataSupport = new ExtractedDatabaseMetaDataImpl.Builder( this ).build();
final IdentifierHelperBuilder identifierHelperBuilder = IdentifierHelperBuilder.from( this );
identifierHelperBuilder.setGloballyQuoteIdentifiers( globalQuoting( cfgService ) );
@ -84,8 +83,10 @@ public class JdbcEnvironmentImpl implements JdbcEnvironment {
identifierHelperBuilder.setNameQualifierSupport( nameQualifierSupport );
IdentifierHelper identifierHelper = null;
ExtractedDatabaseMetaDataImpl.Builder dbMetaDataBuilder = new ExtractedDatabaseMetaDataImpl.Builder( this );
try {
identifierHelper = dialect.buildIdentifierHelper( identifierHelperBuilder, null );
dbMetaDataBuilder.setSupportsNamedParameters( dialect.supportsNamedParameters( null ) );
}
catch (SQLException sqle) {
// should never ever happen
@ -96,6 +97,8 @@ public class JdbcEnvironmentImpl implements JdbcEnvironment {
}
this.identifierHelper = identifierHelper;
this.extractedMetaDataSupport = dbMetaDataBuilder.build();
this.currentCatalog = identifierHelper.toIdentifier(
cfgService.getSetting( AvailableSettings.DEFAULT_CATALOG, StandardConverters.STRING )
);
@ -152,6 +155,7 @@ public class JdbcEnvironmentImpl implements JdbcEnvironment {
this.extractedMetaDataSupport = new ExtractedDatabaseMetaDataImpl.Builder( this )
.apply( databaseMetaData )
.setSupportsNamedParameters( databaseMetaData.supportsNamedParameters() )
.build();
NameQualifierSupport nameQualifierSupport = dialect.getNameQualifierSupport();
@ -226,6 +230,7 @@ public class JdbcEnvironmentImpl implements JdbcEnvironment {
this.extractedMetaDataSupport = new ExtractedDatabaseMetaDataImpl.Builder( this )
.apply( databaseMetaData )
.setConnectionSchemaName( determineCurrentSchemaName( databaseMetaData, serviceRegistry, dialect ) )
.setSupportsNamedParameters(dialect.supportsNamedParameters(databaseMetaData))
.build();
NameQualifierSupport nameQualifierSupport = dialect.getNameQualifierSupport();

View File

@ -0,0 +1,141 @@
/*
* 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.jpa.test.procedure;
import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.NamedStoredProcedureQuery;
import javax.persistence.ParameterMode;
import javax.persistence.StoredProcedureParameter;
import javax.persistence.StoredProcedureQuery;
import javax.persistence.Table;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import org.hibernate.dialect.HSQLDialect;
import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.hibernate.testing.RequiresDialect;
import org.hibernate.testing.TestForIssue;
import static org.junit.Assert.fail;
/**
* @author Andrea Boriero
*/
@TestForIssue(jiraKey = "HHH-10515")
@RequiresDialect(value = HSQLDialect.class)
public class HSQLStoreProcedureTest extends BaseEntityManagerFunctionalTestCase {
EntityManagerFactory entityManagerFactory;
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class[] {User.class};
}
@Before
public void startUp() {
entityManagerFactory = getOrCreateEntityManager().getEntityManagerFactory();
createProcedures( entityManagerFactory );
}
@After
public void tearDown() {
dropProcedures( entityManagerFactory );
}
@Test
public void testNamedStoredProcedureExecution() {
EntityManager em = entityManagerFactory.createEntityManager();
try {
StoredProcedureQuery query = em.createNamedStoredProcedureQuery( "User.inoutproc" );
query.setParameter( "arg1", 1 );
query.execute();
}
finally {
em.close();
}
}
private void createProcedures(EntityManagerFactory emf) {
final String procedureStatement = "CREATE procedure inoutproc (IN arg1 int, OUT res int) " +
"BEGIN ATOMIC set res = arg1 + 1;" +
"END";
executeStatement( emf, procedureStatement );
}
private void dropProcedures(EntityManagerFactory emf) {
executeStatement( emf, "DROP procedure inoutproc" );
}
public void executeStatement(EntityManagerFactory emf, String toExecute) {
final SessionFactoryImplementor sf = emf.unwrap( SessionFactoryImplementor.class );
final JdbcConnectionAccess connectionAccess = sf.getServiceRegistry()
.getService( JdbcServices.class )
.getBootstrapJdbcConnectionAccess();
final Connection conn;
try {
conn = connectionAccess.obtainConnection();
conn.setAutoCommit( false );
try {
Statement statement = conn.createStatement();
statement.execute( toExecute );
try {
statement.close();
}
catch (SQLException e) {
fail( e.getMessage() );
}
}
finally {
try {
conn.commit();
}
catch (SQLException e) {
fail( e.getMessage() );
}
try {
connectionAccess.releaseConnection( conn );
}
catch (SQLException e) {
fail( e.getMessage() );
}
}
}
catch (SQLException e) {
throw new RuntimeException( "Unable to create stored procedures", e );
}
}
@Entity(name = "User")
@NamedStoredProcedureQuery(name = "User.inoutproc", procedureName = "inoutproc", parameters = {
@StoredProcedureParameter(mode = ParameterMode.IN, name = "arg1", type = Integer.class),
@StoredProcedureParameter(mode = ParameterMode.OUT, name = "res", type = Integer.class)
})
@Table(name = "USERS")
public class User {
@Id
@GeneratedValue
private Integer id;
}
}

View File

@ -0,0 +1,91 @@
/**
* 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.jdbc.env;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.env.spi.ExtractedDatabaseMetaData;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseUnitTestCase;
import org.junit.Test;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
/**
* @author Gail Badner
*/
public class NoDatabaseMetaDataTest extends BaseUnitTestCase {
@Test
@TestForIssue( jiraKey = "HHH-10515" )
public void testNoJdbcMetadataDefaultDialect() {
final StandardServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
.applySetting( "hibernate.temp.use_jdbc_metadata_defaults", "false" )
.build();
JdbcEnvironment jdbcEnvironment = serviceRegistry.getService( JdbcEnvironment.class );
ExtractedDatabaseMetaData extractedDatabaseMetaData = jdbcEnvironment.getExtractedDatabaseMetaData();
assertNull( extractedDatabaseMetaData.getConnectionCatalogName() );
assertNull( extractedDatabaseMetaData.getConnectionSchemaName() );
assertTrue( extractedDatabaseMetaData.getTypeInfoSet().isEmpty() );
assertTrue( extractedDatabaseMetaData.getExtraKeywords().isEmpty() );
assertFalse( extractedDatabaseMetaData.supportsNamedParameters() );
assertFalse( extractedDatabaseMetaData.supportsRefCursors() );
assertFalse( extractedDatabaseMetaData.supportsScrollableResults() );
assertFalse( extractedDatabaseMetaData.supportsGetGeneratedKeys() );
assertFalse( extractedDatabaseMetaData.supportsBatchUpdates() );
assertFalse( extractedDatabaseMetaData.supportsDataDefinitionInTransaction() );
assertFalse( extractedDatabaseMetaData.doesDataDefinitionCauseTransactionCommit() );
assertNull( extractedDatabaseMetaData.getSqlStateType() );
assertFalse( extractedDatabaseMetaData.doesLobLocatorUpdateCopy() );
StandardServiceRegistryBuilder.destroy( serviceRegistry );
}
@Test
@TestForIssue( jiraKey = "HHH-10515" )
public void testNoJdbcMetadataDialectOverride() {
final StandardServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
.applySetting( "hibernate.temp.use_jdbc_metadata_defaults", "false" )
.applySetting( AvailableSettings.DIALECT, TestDialect.class.getName() )
.build();
JdbcEnvironment jdbcEnvironment = serviceRegistry.getService( JdbcEnvironment.class );
ExtractedDatabaseMetaData extractedDatabaseMetaData = jdbcEnvironment.getExtractedDatabaseMetaData();
assertNull( extractedDatabaseMetaData.getConnectionCatalogName() );
assertNull( extractedDatabaseMetaData.getConnectionSchemaName() );
assertTrue( extractedDatabaseMetaData.getTypeInfoSet().isEmpty() );
assertTrue( extractedDatabaseMetaData.getExtraKeywords().isEmpty() );
assertTrue( extractedDatabaseMetaData.supportsNamedParameters() );
assertFalse( extractedDatabaseMetaData.supportsRefCursors() );
assertFalse( extractedDatabaseMetaData.supportsScrollableResults() );
assertFalse( extractedDatabaseMetaData.supportsGetGeneratedKeys() );
assertFalse( extractedDatabaseMetaData.supportsBatchUpdates() );
assertFalse( extractedDatabaseMetaData.supportsDataDefinitionInTransaction() );
assertFalse( extractedDatabaseMetaData.doesDataDefinitionCauseTransactionCommit() );
assertNull( extractedDatabaseMetaData.getSqlStateType() );
assertFalse( extractedDatabaseMetaData.doesLobLocatorUpdateCopy() );
StandardServiceRegistryBuilder.destroy( serviceRegistry );
}
public static class TestDialect extends Dialect {
@Override
public boolean supportsNamedParameters(java.sql.DatabaseMetaData databaseMetaData) {
return true;
}
}
}