快速提问:我的客户有这样一种情况,他的数据库带有 varchar 字段,并且相应的 jdbc 代码正在存储/检索布尔值。
我猜布尔值 false 和 true 将被转换为“0”和“1”,但我想对此进行确认(我在网上找不到精确的行为规范,可能取决于每个驱动程序, 在这种情况下是 Oracle)。
我知道我可以自己进行实验,但我想在 stackoverflow.com 上尝试一下!
感谢您的回答,
埃里克。
我同意语义高度特定于数据库的答案,这就是为什么我认为重要的答案是你不应该这样做。JDBC 驱动程序或类似的更改可能会导致隐式行为中断。
相反,如果使用原始 JDBC,让代码获取布尔值并将其转换为适当的字符串('true' 或 'false' 是显而易见的选择),然后将此值设置为 VARCHAR 列。在从 VARCHAR 列读取时,执行相反的操作,抛出或处理 String 不是预期的布尔值之一的异常情况。
感谢您的所有回答,
经过一些实验,我看到 Oracle 确实使用值 0 和 1 将boolean
值存储在varchar2
列中,而 JDBC 代码中没有任何映射。
也就是说,如果我能提供一些背景信息,我们将解决这种情况,即事情会“偶然”发生。我只是想知道,与此同时,应用程序是否会崩溃。
而且,正如我所说,我想看看 stackoverflow 社区从一开始就收听了 Joel/Jeff 播客后的效果!
确实有效!
它适用于 MySQL,该表为 false 和 1 为 true。
输出:
123 => true
456 => false
源代码:
package com.lurz.jdbc;
import java.sql.*;
// Test using Varchar for Boolean
public class BoolTest {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/booltest", "booltest", "booltest");
conn.prepareStatement("create table booltest (id bigint, truefalse varchar(10));").execute();
PreparedStatement stmt = conn.prepareStatement("insert into booltest (id, truefalse) values (?, ?);");
stmt.setLong(1, (long)123);
stmt.setBoolean(2, true);
stmt.execute();
stmt.setLong(1, (long)456);
stmt.setBoolean(2, false);
stmt.execute();
ResultSet rs = conn.createStatement().executeQuery("select id, truefalse from booltest");
while (rs.next()) {
System.out.println(rs.getLong(1)+ " => " + rs.getBoolean(2));
}
}
}
不幸的是,BOOLEAN
语义是高度特定于数据库的。我猜测Oracle 驱动程序会将布尔值转换为VARCHAR
字段为 " true
" 和 " false
",而不是0
and 1
,但您应该自己验证这一点。
可以使用 VARCHAR(2) 在 Oracle 中表示 Java 布尔值。但是,我建议不要这样做,并建议您改用 NUMBER(1)。如果布尔列上有一个索引并且您在 WHERE 子句中使用它,Oracle 将对其应用 to_number 数字函数以将“0”转换为 0 或将“1”转换为 1。该函数的应用会否定使用该列上的索引,将导致您进行全表扫描。