使用 H2 内存数据库测试我的 DAL 目前不起作用,因为数据 tye BINARY 被转换为 VARBINARY:
CREATE TABLE test (
pk_user_id INT AUTO_INCREMENT(1, 1) PRIMARY KEY,
uuid BINARY(16) UNIQUE NOT NULL
);
如果我检查具有预期数据类型的列是否存在,则会导致错误的数据类型:
2017-03-20 16:24:48 持久性.数据库.表检查 意外列 (UUID) 或类型 (-3, VARBINARY)
tl;博士
导致错误的数据类型
不,不是错误的类型,只是同一类型的另一个标签。
二进制类型有五个同义词:{ BINARY | VARBINARY | LONGVARBINARY | RAW | BYTEA }
所有五个名称都表示相同的类型,并且在 Java 中都映射到byte[]
。
数据类型名称的同义词
数据类型在 SQL 世界中没有严格定义。SQL 规范只定义了几种类型。许多数据库系统通过许多名称定义许多类型。为了使客户更容易从一个数据库系统移植到他们的数据库系统,数据库供应商通常实现数据类型的同义词,以匹配其竞争对手的类型兼容的同义词。
H2 像许多其他数据库系统一样,数据类型有多个名称。 对于将整个值加载到内存中的二进制类型,H2 为同一单一数据类型定义了五个名称:
{ 二进制 |瓦二进制 |长瓦二进制 |原始 |拜蒂亚 }
同样,H2 通过五个同义词中的任何一个提供有符号的 32 位整数数据类型:
{ 国际 |整数 |中英 |INT4 |签名 }
因此,您可以指定这五个名称中的任何一个,但您将获得相同的效果,即 H2 提供的相同基础数据类型。
事实上,我自己运行代码来使用二进制类型的这五个名称中的每一个来创建列。在每种情况下,列名的元数据都将数据类型报告为VARBINARY
。
虽然在内部使用这五个中的哪一个来跟踪列的数据类型并不重要,但我对VARBINARY
的使用感到有些惊讶,因为 H2 数据类型文档页面标题将这种类型宣传为BINARY
。因此,我希望默认情况下在元数据中使用BINARY
。如果您真的关心,您可能希望为此记录错误/问题,因为似乎文档标题应该更改为VARBINARY
或者 H2 的数据类型的内部标签应该更改为BINARY
.
下面是一些示例 Java JDBC 代码,用于确认您在问题中报告的行为。
我建议您更改数据类型检查代码以查找此数据类型的五个可能名称中的任何一个,而不是仅检查一个特定名称。
try {
Class.forName ( "org.h2.Driver" );
} catch ( ClassNotFoundException e ) {
e.printStackTrace ( );
}
try ( Connection conn = DriverManager.getConnection ( "jdbc:h2:mem:" ) ;
Statement stmt = conn.createStatement ( ) ; ) {
String tableName = "test_";
String sql = "CREATE TABLE " + tableName + " (n" +
" pk_user_id_ INT AUTO_INCREMENT(1, 1) PRIMARY KEY,n" +
" uuid_ BINARY(16) UNIQUE NOT NULLn" +
");";
// String sql = "CREATE TABLE " + tableName +
// "(" +
// " id_ INT AUTO_INCREMENT(1, 1) PRIMARY KEY, " +
// " binary_id_ BINARY(16) UNIQUE NOT NULL, " +
// " uuid_id_ UUID, " +
// " age_ INTEGER " + ")";
stmt.execute ( sql );
// List tables
DatabaseMetaData md = conn.getMetaData ( );
try ( ResultSet rs = md.getTables ( null, null, null, null ) ) {
while ( rs.next ( ) ) {
System.out.println ( rs.getString ( 3 ) );
}
}
// List columns of our table.
try ( ResultSet rs = md.getColumns ( null, null, tableName.toUpperCase ( Locale.US ), null ) ) {
System.out.println ( "Columns of table: " + tableName );
while ( rs.next ( ) ) {
System.out.println ( rs.getString ( 4 ) + " | " + rs.getString ( 5 ) + " | " + rs.getString ( 6 ) ); // COLUMN_NAME, DATA_TYPE , TYPE_NAME.
}
}
} catch ( SQLException e ) {
e.printStackTrace ( );
}
目录
排序规则
。
用户
视图
测试_
表的列数:test_
PK_USER_ID_ | 4 |整数
UUID_ | -3 |瓦二进制
技巧:
- 向所有 SQL 名称添加尾随下划线可避免与 SQL 世界中发现的一千多个保留字中的任何一个发生冲突。SQL 规范承诺 SQL 系统永远不会使用尾随下划线。例如,您使用的列名
uuid
可能与 H2 的UUID
数据类型冲突。 - 您的代码
uuid BINARY(16)
表明您正在尝试存储 UUID(一个 128 位值,其中某些位定义了语义)。请注意,H2 原生支持 UUID 作为数据类型,Postgres 和其他一些数据库系统也是如此。所以把uuid_ BINARY(16)
改成uuid_ UUID
.