1. 概述
在使用Java JDBC時,你是否有過這樣的疑問:MySQL里的數據類型到底該選擇哪種Java類型與之對應?本篇將為你揭開這個答案。
2. 類型映射
java.sql.Types定義了常用數據庫(MySQL、Oracle、DB2等)所用到的數據類型,官名也叫JDBC類型。每個數據庫產品的數據類型定義各不相同,但都有JDBC類型與之對應,如MySQL的BIGINT-->JDBC的BIGINT。
而每個JDBC類型,都有默認的Java類型與之對應,即ResultSet.getObject()返回Object的具體類型,如JDBC的BIGINT-->Java的java.lang.Long;JDBC的BIGINT UNSIGNED-->Java的 java.math.BigInteger。
我們可以通過ResultSet.getMetaData().getColumnTypeName(columnIndex)獲取字段的JDBC類型,通過ResultSet.getMetaData().getColumnClassName(columnIndex)獲取字段的Java類型。
下圖展示了MySQL類型類型、JDBC類型、Java類型的映射關系(源自:5.3 Java, JDBC and MySQL Types)。
| MySQL數據類型 | JDBC類型(getColumnTypeName) | 默認返回的Java類型(getColumnClassName) |
|---|---|---|
BIT(1) (new in MySQL-5.0) |
BIT |
java.lang.Boolean |
BIT( > 1) (new in MySQL-5.0) |
BIT |
byte[] |
TINYINT |
TINYINT |
java.lang.Boolean if the configuration property tinyInt1isBit is set to true (the default) and the storage size is 1, or java.lang.Integer if not. |
BOOL, BOOLEAN |
TINYINT |
See TINYINT, above as these are aliases for TINYINT(1), currently. |
SMALLINT[(M)] [UNSIGNED] |
SMALLINT [UNSIGNED] |
java.lang.Integer (regardless of whether it is UNSIGNED or not) |
MEDIUMINT[(M)] [UNSIGNED] |
MEDIUMINT [UNSIGNED] |
java.lang.Integer (regardless of whether it is UNSIGNED or not) |
INT,INTEGER[(M)] [UNSIGNED] |
INTEGER [UNSIGNED] |
java.lang.Integer, if UNSIGNED java.lang.Long |
BIGINT[(M)] [UNSIGNED] |
BIGINT [UNSIGNED] |
java.lang.Long, if UNSIGNED java.math.BigInteger |
FLOAT[(M,D)] |
FLOAT |
java.lang.Float |
DOUBLE[(M,B)] |
DOUBLE |
java.lang.Double |
DECIMAL[(M[,D])] |
DECIMAL |
java.math.BigDecimal |
DATE |
DATE |
java.sql.Date |
DATETIME |
DATETIME |
java.sql.Timestamp |
TIMESTAMP[(M)] |
TIMESTAMP |
java.sql.Timestamp |
TIME |
TIME |
java.sql.Time |
YEAR[(2|4)] |
YEAR |
If yearIsDateType configuration property is set to false, then the returned object type is java.sql.Short. If set to true (the default), then the returned object is of type java.sql.Datewith the date set to January 1st, at midnight. |
CHAR(M) |
CHAR |
java.lang.String (unless the character set for the column is BINARY, then byte[] is returned. |
VARCHAR(M) [BINARY] |
VARCHAR |
java.lang.String (unless the character set for the column is BINARY, then byte[] is returned. |
BINARY(M) |
BINARY |
byte[] |
VARBINARY(M) |
VARBINARY |
byte[] |
TINYBLOB |
TINYBLOB |
byte[] |
TINYTEXT |
VARCHAR |
java.lang.String |
BLOB |
BLOB |
byte[] |
TEXT |
VARCHAR |
java.lang.String |
MEDIUMBLOB |
MEDIUMBLOB |
byte[] |
MEDIUMTEXT |
VARCHAR |
java.lang.String |
LONGBLOB |
LONGBLOB |
byte[] |
LONGTEXT |
VARCHAR |
java.lang.String |
ENUM('value1','value2',...) |
CHAR |
java.lang.String |
SET('value1','value2',...) |
CHAR |
java.lang.String |
3. 類型轉換
上面我們看到MySQL的BIGINT默認轉為Java的java.lang.Long,那是不是就不能轉為String或其他數值類型了?答案是否定的!MySQL的JDBC(Connector/J)在字段類型與Java類型之間的轉換是比較靈活的。一般來說,任何字段類型都可以轉換為java.lang.String,任何數值字段類型都可以轉換為Java的數據類型(當然會出現四舍五入、溢出、精度丟失的問題)。
下圖展示了MySQL JDBC允許的跨類型相互轉換。
| MySQL數據類型 | 可以被轉換的Java類型 |
|---|---|
CHAR, VARCHAR, BLOB, TEXT, ENUM, and SET |
java.lang.String, java.io.InputStream, java.io.Reader, java.sql.Blob, java.sql.Clob |
FLOAT, REAL, DOUBLE PRECISION, NUMERIC, DECIMAL, TINYINT, SMALLINT, MEDIUMINT, INTEGER, BIGINT |
java.lang.String, java.lang.Short, java.lang.Integer, java.lang.Long, java.lang.Double, java.math.BigDecimal |
DATE, TIME, DATETIME, TIMESTAMP |
java.lang.String, java.sql.Date, java.sql.Timestamp |
4. 總結
MySQL JDBC對每種字段類型,都有相應的Java類型與之對應,也可以轉換為其他Java類型。但這種轉換還不夠靈活,如TIMESTAMP與java.util.Date就轉換不了,只能人工轉換。這里推薦使用MyBatis,它內置了許多TypeHander,支持各種基礎數據類型間的轉換(xxxTypeHandler),也支持自定義數據類型轉換。

參考:
