是否可以使用Java JDBC在varchar字段中存储和检索布尔值?

时间:2020-03-06 14:19:42  来源:igfitidea点击:

一个简单的问题:我的客户遇到这样的情况:他的数据库带有varchar字段,并且相应的jdbc代码正在存储/检索布尔值。

我想布尔值false和true将被转换为" 0"和" 1",但我想对此进行确认(我无法在线找到确切的行为规范,也许取决于每个驱动程序,在这种情况下为Oracle)。

我知道我可以自己做实验,但是我想在stackoverflow.com上尝试一下!

感谢回答,

埃里克。

解决方案

不幸的是," BOOLEAN"语义是高度特定于数据库的。我猜想Oracle驱动程序将布尔值转换为VARCHAR字段的是true和false,而不是0和1,但是我们应该自己验证一下。

我同意这样的答案,即语义是高度特定于数据库的,这就是为什么我认为重要的答案是我们不应该这样做。 JDBC驱动程序中的更改或者类似更改可能导致隐式行为中断。

相反,如果使用原始JDBC,则让代码接受布尔值并将其转换为适当的字符串(" true"或者" false"是显而易见的选择),然后将此值设置为VARCHAR列。从VARCHAR列读取时,执行相反的操作,引发或者处理异常情况,即String不是所期望的布尔值之一。

它与MySQL一起使用,该表的false值为0,true值为1.

输出:

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));
      }  
   }
}

感谢所有回答,

经过一些试验,我发现Oracle确实使用了0和1值将boolean值存储在varchar2列中,而JDBC代码中没有任何映射。

就是说,如果我可以提供一些背景信息,我们将解决这种情况,即事情会"偶然地"起作用。我只是想知道在此期间,该应用程序是否会崩溃。

而且,就像我说的那样,我想看看从一开始就听过Joel / Jeff播客之后stackoverflow社区的效果如何!

确实有效!