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:
parent
6b2972884a
commit
8bf9791254
|
@ -24,8 +24,10 @@
|
||||||
package org.hibernate.test.annotations.dataTypes;
|
package org.hibernate.test.annotations.dataTypes;
|
||||||
|
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
|
import java.sql.DatabaseMetaData;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
import java.sql.Statement;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
@ -43,8 +45,12 @@ import static org.junit.Assert.assertTrue;
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
@RequiresDialectFeature( DialectChecks.SupportsExpectedLobUsagePattern.class )
|
@RequiresDialectFeature(DialectChecks.SupportsExpectedLobUsagePattern.class)
|
||||||
public class BasicOperationsTest extends BaseCoreFunctionalTestCase {
|
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
|
@Override
|
||||||
protected Class<?>[] getAnnotatedClasses() {
|
protected Class<?>[] getAnnotatedClasses() {
|
||||||
return new Class[] { SomeEntity.class, SomeOtherEntity.class };
|
return new Class[] { SomeEntity.class, SomeOtherEntity.class };
|
||||||
|
@ -55,43 +61,95 @@ public class BasicOperationsTest extends BaseCoreFunctionalTestCase {
|
||||||
Date now = new Date();
|
Date now = new Date();
|
||||||
|
|
||||||
Session s = openSession();
|
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)
|
s.doWork( new ValidateSomeEntityColumns() );
|
||||||
validateColumn( connection, "TIMEDATA", java.sql.Types.TIME );
|
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();
|
s.beginTransaction();
|
||||||
SomeEntity someEntity = new SomeEntity( now );
|
SomeEntity someEntity = new SomeEntity( now );
|
||||||
SomeOtherEntity someOtherEntity = new SomeOtherEntity(1);
|
SomeOtherEntity someOtherEntity = new SomeOtherEntity( 1 );
|
||||||
s.save( someEntity );
|
s.save( someEntity );
|
||||||
s.save( someOtherEntity );
|
s.save( someOtherEntity );
|
||||||
s.getTransaction().commit();
|
s.getTransaction().commit();
|
||||||
s.close();
|
s.close();
|
||||||
|
|
||||||
s = openSession();
|
s = openSession();
|
||||||
|
|
||||||
|
s.doWork( new ValidateRowCount( SOME_ENTITY_TABLE_NAME, 1 ) );
|
||||||
|
s.doWork( new ValidateRowCount( SOME_OTHER_ENTITY_TABLE_NAME, 1 ) );
|
||||||
|
|
||||||
s.beginTransaction();
|
s.beginTransaction();
|
||||||
s.delete( someEntity );
|
s.delete( someEntity );
|
||||||
s.delete( someOtherEntity );
|
s.delete( someOtherEntity );
|
||||||
s.getTransaction().commit();
|
s.getTransaction().commit();
|
||||||
|
|
||||||
|
s.doWork( new ValidateRowCount( SOME_ENTITY_TABLE_NAME, 0 ) );
|
||||||
|
s.doWork( new ValidateRowCount( SOME_OTHER_ENTITY_TABLE_NAME, 0 ) );
|
||||||
|
|
||||||
s.close();
|
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 );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
* Boston, MA 02110-1301 USA
|
* Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
package org.hibernate.test.annotations.dataTypes;
|
package org.hibernate.test.annotations.dataTypes;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import javax.persistence.Access;
|
import javax.persistence.Access;
|
||||||
import javax.persistence.AccessType;
|
import javax.persistence.AccessType;
|
||||||
|
@ -34,8 +35,6 @@ import javax.persistence.Temporal;
|
||||||
import javax.persistence.TemporalType;
|
import javax.persistence.TemporalType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO : javadoc
|
|
||||||
*
|
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
@Entity
|
@Entity
|
||||||
|
@ -44,11 +43,11 @@ import javax.persistence.TemporalType;
|
||||||
public class SomeEntity {
|
public class SomeEntity {
|
||||||
@Id
|
@Id
|
||||||
@Temporal(TemporalType.DATE)
|
@Temporal(TemporalType.DATE)
|
||||||
@Column(name = "ID")
|
@Column(name = "ID")
|
||||||
private java.util.Date id;
|
private java.util.Date id;
|
||||||
@Column(name = "TIMEDATA")
|
@Column(name = "TIMEDATA")
|
||||||
private java.sql.Time timeData;
|
private java.sql.Time timeData;
|
||||||
@Column(name = "TSDATA")
|
@Column(name = "TSDATA")
|
||||||
private java.sql.Timestamp tsData;
|
private java.sql.Timestamp tsData;
|
||||||
@Lob
|
@Lob
|
||||||
private Byte[] byteData;
|
private Byte[] byteData;
|
||||||
|
@ -100,5 +99,4 @@ public class SomeEntity {
|
||||||
public void setByteData(Byte[] byteData) {
|
public void setByteData(Byte[] byteData) {
|
||||||
this.byteData = byteData;
|
this.byteData = byteData;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
* Boston, MA 02110-1301 USA
|
* Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
package org.hibernate.test.annotations.dataTypes;
|
package org.hibernate.test.annotations.dataTypes;
|
||||||
|
|
||||||
import javax.persistence.Access;
|
import javax.persistence.Access;
|
||||||
import javax.persistence.AccessType;
|
import javax.persistence.AccessType;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
|
@ -30,37 +31,36 @@ import javax.persistence.Enumerated;
|
||||||
import javax.persistence.Id;
|
import javax.persistence.Id;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO : javadoc
|
|
||||||
*
|
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
@Entity
|
@Entity
|
||||||
@Access(AccessType.FIELD)
|
@Access(AccessType.FIELD)
|
||||||
public class SomeOtherEntity {
|
public class SomeOtherEntity {
|
||||||
@Id
|
@Id
|
||||||
protected int id;
|
protected int id;
|
||||||
protected boolean booleanData;
|
protected boolean booleanData;
|
||||||
protected byte byteData;
|
protected byte byteData;
|
||||||
protected char characterData;
|
// setting a arbitrary character here to make this test also pass against PostgreSQL
|
||||||
protected short shortData;
|
// PostgreSQL throws otherwise an exception when persisting the null value
|
||||||
protected int integerData;
|
// org.postgresql.util.PSQLException: ERROR: invalid byte sequence for encoding "UTF8": 0x00
|
||||||
protected long longData;
|
protected char characterData = 'a';
|
||||||
protected double doubleData;
|
protected short shortData;
|
||||||
protected float floatData;
|
protected int integerData;
|
||||||
@Enumerated(EnumType.STRING)
|
protected long longData;
|
||||||
protected Grade grade;
|
protected double doubleData;
|
||||||
|
protected float floatData;
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
|
protected Grade grade;
|
||||||
|
|
||||||
|
|
||||||
public SomeOtherEntity()
|
public SomeOtherEntity() {
|
||||||
{
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public SomeOtherEntity(int id)
|
public SomeOtherEntity(int id) {
|
||||||
{
|
this.id = id;
|
||||||
this.id = id;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public SomeOtherEntity(
|
public SomeOtherEntity(
|
||||||
int id,
|
int id,
|
||||||
boolean booleanData,
|
boolean booleanData,
|
||||||
byte byteData,
|
byte byteData,
|
||||||
|
@ -71,15 +71,15 @@ public class SomeOtherEntity {
|
||||||
double doubleData,
|
double doubleData,
|
||||||
float floatData) {
|
float floatData) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.booleanData = booleanData;
|
this.booleanData = booleanData;
|
||||||
this.byteData = byteData;
|
this.byteData = byteData;
|
||||||
this.characterData = characterData;
|
this.characterData = characterData;
|
||||||
this.shortData = shortData;
|
this.shortData = shortData;
|
||||||
this.integerData = integerData;
|
this.integerData = integerData;
|
||||||
this.longData = longData;
|
this.longData = longData;
|
||||||
this.doubleData = doubleData;
|
this.doubleData = doubleData;
|
||||||
this.floatData = floatData;
|
this.floatData = floatData;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer getId() {
|
public Integer getId() {
|
||||||
return id;
|
return id;
|
||||||
|
@ -144,5 +144,4 @@ public class SomeOtherEntity {
|
||||||
public void setGrade(Grade grade) {
|
public void setGrade(Grade grade) {
|
||||||
this.grade = grade;
|
this.grade = grade;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue