数据库的boolean值是一个令人头疼的问题,涉及到多方面的问题。
数据库中的boolean字段,以什么方式命名?通常会要求boolean值以is开头,比如阿里的数据库设计规范强制要求boolean型以is_
开头,比如is_deleted
。这确实可以很直观的让人知道某个字段的类型,我也很喜欢这样。
但是命名不仅仅是在数据库里面,JavaBean里面如何命名呢?为了统一性(特别是使用工具从数据库生成Java类),JavaBean里的属性名应该和数据库字段名一致,当然是isDeleted
。
那么问题来了,JavaBean的get、set方法如何写呢?如果用开发工具(如IntelliJ IDEA)生成,会是这样:
public class User {
private Boolean isDisabled;
public Boolean getDisabled() {
return isDisabled;
}
public void setDisabled(Boolean disabled) {
isDisabled = disabled;
}
}
有些生成工具产生如下代码也不要奇怪:
public class User {
private Boolean isDisabled;
public Boolean getIsDisabled() {
return this.isDisabled;
}
public void setIsDisabled(Boolean isDisabled) {
this.isDisabled = isDisabled;
}
}
如果使用原生类型boolean
而非对象类型Boolean
,则代码如下:
public class User {
private boolean isDisabled;
public boolean isDisabled() {
return this.isDisabled;
}
public void setDisabled(boolean disabled) {
this.isDisabled = disabled;
}
}
再用jackson生成JSON,会是{disabled:false}
或{isDisabled:false}
。
于是数据库isDisabled
,JavagetDisabled()
isDisabled()
getIsDisabled()
,JSONdisabled
isDisabled
。是不是有点凌乱?
太混乱了,所以有很多开发规范里禁止JavaBean属性使用is
开头。
数据库说要is
开头,JavaBean说不要is
开头,到底要不要?也许可以让数据库的字段用is
开头,在JavaBean里则去掉is
。这是一个办法,但从数据库自动生成JavaBean的时候,就要手动改了。而且JavaBean、JSON里都没有is开头,在数据库里又突然又有is开头,也是一种混乱。
最后的结论是,都不要is
开头,且boolean型不能为空。JavaBean用原生类型boolean
而不是Boolean
。这样数据库disabled
,JavaisDisabled()
,JSONdisabled
,这样就简单明了多了。
另:可为空的Boolean可以考虑用char(1)
,如性别(m:男,f:女,n:保密)。
虽然boolean型是SQL标准的数据类型,但很多数据库都没有提供boolean类型,理由是这个数据类型太容易代替了,没有必要专门用一个数据类型。比如用char(1)或者int。
可代替是可代替,那实际使用中,怎么代替才是最佳实践呢?
Hibernate是这样处理的:
int
或者tinyint
),则0
表示false
,1
表示true
。char(1)
),则N/n
表示false
, Y/y
表示true
,或者F/f
表示false
, T/t
表示true
。很显然使用数值型比较直观,毕竟和c语言的规则一致,计算机一贯的传统。
字符型则稍显混乱,当然字符型也可以用0和1,特别是在oracle中用char(1)
比用number(1)
更节省空间。char(1)
占一个字节,number(1)
占两个字节。在其它没有1字节的数值型数据库中,也是这样(如DB2)。
用char(1)
还一个问题,就是数据库自动生成JavaBean时,无法判断是字符型还是boolean型。特别时字段不以is
开头,就更无法自动判断了,这对自动生成代码很不友好。众所周知,自动生成代码在开发里面有着很高地位,没有人愿意把时间花在重复的、没有意义的事情上面。
MySQL中,有boolean
类型,但这个类型是tinyint(1)
的同义词,就是说boolean也是用数值存储的。
阿里的数据库设计规范也是要求使用tinyint(1)
存储boolean类型。
数据库管理工具liquibase
的规则是有boolean类型的直接用,没有的用bit或者数值代替:
MySQLDatabase: BIT(1)
SQLiteDatabase: BOOLEAN
H2Database: BOOLEAN
PostgresDatabase: BOOLEAN
UnsupportedDatabase: BOOLEAN
DB2Database: SMALLINT
MSSQLDatabase: [bit]
OracleDatabase: NUMBER(1)
HsqlDatabase: BOOLEAN
FirebirdDatabase: SMALLINT
DerbyDatabase: SMALLINT
InformixDatabase: BOOLEAN
SybaseDatabase: BIT
SybaseASADatabase: BIT
liquibase
在MySQL中使用BIT(1)
,没有直接用MySQL的boolean类型,这个有点奇怪,可能liquibase
认为MySQL的boolean是假的(实际是tinyint(1)
),还不如用BIT(1)
。咱就不和数据库较这个劲了,直接用MySQL的boolean
,数据库说啥就是啥,它总比我们了解它自己吧,总不能让我们吃什么大亏。
如此看来,并不好逆流而动用char(1)
作为boolean。至少看在代码自动生成的份上,开发环境上用数值做boolean(一般是MySQL,直接用bool
类型,数据库自动转为tinyint(1)
)。生成其它数据库脚本时,如果为了方便(char(1)
所有的数据库都有)或者节省存储空间,将boolean
转成char(1)
也许不是什么大问题(MyBatis会映射成BIT类型,不知能否操作char(1)
)。