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;
@ -43,8 +45,12 @@ import static org.junit.Assert.assertTrue;
/**
* @author Steve Ebersole
*/
@RequiresDialectFeature( DialectChecks.SupportsExpectedLobUsagePattern.class )
@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,43 +61,95 @@ public class BasicOperationsTest extends BaseCoreFunctionalTestCase {
Date now = new Date();
Session s = openSession();
s.doWork(
new Work() {
public void execute(Connection connection) throws SQLException {
// id -> java.util.Date (DATE - becase of explicit TemporalType)
validateColumn( connection, "ID", java.sql.Types.DATE );
// timeData -> java.sql.Time (TIME)
validateColumn( connection, "TIMEDATA", java.sql.Types.TIME );
s.doWork( new ValidateSomeEntityColumns() );
s.doWork( new ValidateRowCount( SOME_ENTITY_TABLE_NAME, 0 ) );
s.doWork( new ValidateRowCount( SOME_OTHER_ENTITY_TABLE_NAME, 0 ) );
// tsData -> java.sql.Timestamp (TIMESTAMP)
validateColumn( connection, "TSDATA", java.sql.Types.TIMESTAMP );
}
private void validateColumn(Connection connection, String columnName, int expectedJdbcTypeCode)
throws SQLException {
ResultSet columnInfo = connection.getMetaData().getColumns( null, null, "SOMEENTITY", columnName );
assertTrue( columnInfo.next() );
int dataType = columnInfo.getInt( "DATA_TYPE" );
columnInfo.close();
assertEquals( columnName, JdbcTypeNameMapper.getTypeName(expectedJdbcTypeCode), JdbcTypeNameMapper.getTypeName(dataType) );
}
}
);
s.beginTransaction();
SomeEntity someEntity = new SomeEntity( now );
SomeOtherEntity someOtherEntity = new SomeOtherEntity(1);
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 );
// timeData -> java.sql.Time (TIME)
validateColumn( connection, "TIMEDATA", java.sql.Types.TIME );
// tsData -> java.sql.Timestamp (TIMESTAMP)
validateColumn( connection, "TSDATA", java.sql.Types.TIMESTAMP );
}
private void validateColumn(Connection connection, String columnName, int expectedJdbcTypeCode)
throws SQLException {
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 )
);
}
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
@ -44,11 +43,11 @@ import javax.persistence.TemporalType;
public class SomeEntity {
@Id
@Temporal(TemporalType.DATE)
@Column(name = "ID")
@Column(name = "ID")
private java.util.Date id;
@Column(name = "TIMEDATA")
@Column(name = "TIMEDATA")
private java.sql.Time timeData;
@Column(name = "TSDATA")
@Column(name = "TSDATA")
private java.sql.Timestamp tsData;
@Lob
private Byte[] byteData;
@ -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,37 +31,36 @@ import javax.persistence.Enumerated;
import javax.persistence.Id;
/**
* TODO : javadoc
*
* @author Steve Ebersole
*/
@Entity
@Access(AccessType.FIELD)
public class SomeOtherEntity {
@Id
protected int id;
protected boolean booleanData;
protected byte byteData;
protected char characterData;
protected short shortData;
protected int integerData;
protected long longData;
protected double doubleData;
protected float floatData;
@Enumerated(EnumType.STRING)
protected Grade grade;
protected int id;
protected boolean booleanData;
protected byte byteData;
// 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;
protected double doubleData;
protected float floatData;
@Enumerated(EnumType.STRING)
protected Grade grade;
public SomeOtherEntity()
{
}
public SomeOtherEntity() {
}
public SomeOtherEntity(int id)
{
this.id = id;
}
public SomeOtherEntity(int id) {
this.id = id;
}
public SomeOtherEntity(
public SomeOtherEntity(
int id,
boolean booleanData,
byte byteData,
@ -71,15 +71,15 @@ public class SomeOtherEntity {
double doubleData,
float floatData) {
this.id = id;
this.booleanData = booleanData;
this.byteData = byteData;
this.characterData = characterData;
this.shortData = shortData;
this.integerData = integerData;
this.longData = longData;
this.doubleData = doubleData;
this.floatData = floatData;
}
this.booleanData = booleanData;
this.byteData = byteData;
this.characterData = characterData;
this.shortData = shortData;
this.integerData = integerData;
this.longData = longData;
this.doubleData = doubleData;
this.floatData = floatData;
}
public Integer getId() {
return id;
@ -144,5 +144,4 @@ public class SomeOtherEntity {
public void setGrade(Grade grade) {
this.grade = grade;
}
}