HHH-6828 Taking case sensitivity into account when accessing the database metadata

Also extending the test and formatting the code.
This commit is contained in:
Hardy Ferentschik 2011-11-17 17:51:30 +01:00
parent 6b2972884a
commit 8bf9791254
3 changed files with 116 additions and 61 deletions

View File

@ -24,8 +24,10 @@
package org.hibernate.test.annotations.dataTypes;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Date;
import org.junit.Test;
@ -45,6 +47,10 @@ import static org.junit.Assert.assertTrue;
*/
@RequiresDialectFeature(DialectChecks.SupportsExpectedLobUsagePattern.class)
public class BasicOperationsTest extends BaseCoreFunctionalTestCase {
private static final String SOME_ENTITY_TABLE_NAME = "SOMEENTITY";
private static final String SOME_OTHER_ENTITY_TABLE_NAME = "SOMEOTHERENTITY";
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class[] { SomeEntity.class, SomeOtherEntity.class };
@ -55,8 +61,37 @@ public class BasicOperationsTest extends BaseCoreFunctionalTestCase {
Date now = new Date();
Session s = openSession();
s.doWork(
new Work() {
s.doWork( new ValidateSomeEntityColumns() );
s.doWork( new ValidateRowCount( SOME_ENTITY_TABLE_NAME, 0 ) );
s.doWork( new ValidateRowCount( SOME_OTHER_ENTITY_TABLE_NAME, 0 ) );
s.beginTransaction();
SomeEntity someEntity = new SomeEntity( now );
SomeOtherEntity someOtherEntity = new SomeOtherEntity( 1 );
s.save( someEntity );
s.save( someOtherEntity );
s.getTransaction().commit();
s.close();
s = openSession();
s.doWork( new ValidateRowCount( SOME_ENTITY_TABLE_NAME, 1 ) );
s.doWork( new ValidateRowCount( SOME_OTHER_ENTITY_TABLE_NAME, 1 ) );
s.beginTransaction();
s.delete( someEntity );
s.delete( someOtherEntity );
s.getTransaction().commit();
s.doWork( new ValidateRowCount( SOME_ENTITY_TABLE_NAME, 0 ) );
s.doWork( new ValidateRowCount( SOME_OTHER_ENTITY_TABLE_NAME, 0 ) );
s.close();
}
// verify all the expected columns are created
class ValidateSomeEntityColumns implements Work {
public void execute(Connection connection) throws SQLException {
// id -> java.util.Date (DATE - becase of explicit TemporalType)
validateColumn( connection, "ID", java.sql.Types.DATE );
@ -70,28 +105,51 @@ public class BasicOperationsTest extends BaseCoreFunctionalTestCase {
private void validateColumn(Connection connection, String columnName, int expectedJdbcTypeCode)
throws SQLException {
ResultSet columnInfo = connection.getMetaData().getColumns( null, null, "SOMEENTITY", columnName );
DatabaseMetaData meta = connection.getMetaData();
// DBs treat the meta information differently, in particular case sensitivity.
// We need to use the meta information to find out how to treat names
String tableNamePattern = generateFinalNamePattern( meta, SOME_ENTITY_TABLE_NAME );
String columnNamePattern = generateFinalNamePattern( meta, columnName );
ResultSet columnInfo = meta.getColumns( null, null, tableNamePattern, columnNamePattern );
assertTrue( columnInfo.next() );
int dataType = columnInfo.getInt( "DATA_TYPE" );
columnInfo.close();
assertEquals( columnName, JdbcTypeNameMapper.getTypeName(expectedJdbcTypeCode), JdbcTypeNameMapper.getTypeName(dataType) );
}
}
assertEquals(
columnName,
JdbcTypeNameMapper.getTypeName( expectedJdbcTypeCode ),
JdbcTypeNameMapper.getTypeName( dataType )
);
s.beginTransaction();
SomeEntity someEntity = new SomeEntity( now );
SomeOtherEntity someOtherEntity = new SomeOtherEntity(1);
s.save( someEntity );
s.save( someOtherEntity );
s.getTransaction().commit();
s.close();
}
s = openSession();
s.beginTransaction();
s.delete( someEntity );
s.delete( someOtherEntity );
s.getTransaction().commit();
s.close();
private String generateFinalNamePattern(DatabaseMetaData meta, String name) throws SQLException {
if ( meta.storesLowerCaseIdentifiers() ) {
return name.toLowerCase();
}
else {
return name;
}
}
}
// verify we have the right amount of columns
class ValidateRowCount implements Work {
private final int expectedRowCount;
private final String table;
public ValidateRowCount(String table, int count) {
this.expectedRowCount = count;
this.table = table;
}
public void execute(Connection connection) throws SQLException {
Statement st = connection.createStatement();
ResultSet result = st.executeQuery( "SELECT COUNT(*) FROM " + table );
result.next();
int rowCount = result.getInt( 1 );
assertEquals( "Unexpected row count", expectedRowCount, rowCount );
}
}
}

View File

@ -22,6 +22,7 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.test.annotations.dataTypes;
import java.util.Date;
import javax.persistence.Access;
import javax.persistence.AccessType;
@ -34,8 +35,6 @@ import javax.persistence.Temporal;
import javax.persistence.TemporalType;
/**
* TODO : javadoc
*
* @author Steve Ebersole
*/
@Entity
@ -100,5 +99,4 @@ public class SomeEntity {
public void setByteData(Byte[] byteData) {
this.byteData = byteData;
}
}

View File

@ -22,6 +22,7 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.test.annotations.dataTypes;
import javax.persistence.Access;
import javax.persistence.AccessType;
import javax.persistence.Entity;
@ -30,8 +31,6 @@ import javax.persistence.Enumerated;
import javax.persistence.Id;
/**
* TODO : javadoc
*
* @author Steve Ebersole
*/
@Entity
@ -41,7 +40,10 @@ public class SomeOtherEntity {
protected int id;
protected boolean booleanData;
protected byte byteData;
protected char characterData;
// setting a arbitrary character here to make this test also pass against PostgreSQL
// PostgreSQL throws otherwise an exception when persisting the null value
// org.postgresql.util.PSQLException: ERROR: invalid byte sequence for encoding "UTF8": 0x00
protected char characterData = 'a';
protected short shortData;
protected int integerData;
protected long longData;
@ -51,12 +53,10 @@ public class SomeOtherEntity {
protected Grade grade;
public SomeOtherEntity()
{
public SomeOtherEntity() {
}
public SomeOtherEntity(int id)
{
public SomeOtherEntity(int id) {
this.id = id;
}
@ -144,5 +144,4 @@ public class SomeOtherEntity {
public void setGrade(Grade grade) {
this.grade = grade;
}
}