Поддерживаемые типы данных
Во время предыдущих трех уровней мы немного познакомились с Hibernate. Настало время зайти на второй круг. Теперь мы начнем изучать тоже самое, только глубже. И начнем мы с маппинга полей Entity-класса на колонки таблиц в базе данных.
Как ты уже знаешь, маппинг поля в Entity классе на колонку выполняется с помощью аннотации @Column. И теперь вопрос: а поля каких типов можно замапить такой аннотацией?
Все типы данных в Java можно разбить на три группы:
- Тип достаточно простой и его легко сохранить в базу данных.
- Тип сложный и для него нужно писать специальный конвертор.
- Тип очень сложный и для хранения его значений нужна отдельная таблица.
К простым типам, про которые Hibernate знает, как их сохранять, относятся такие:
Типы в языке Java | package | Примеры классов |
---|---|---|
Примитивные типы языка Java | boolean, int, double и т. п. | |
Обертки над примитивами | java.lang | Boolean, Integer, Double и т. п. |
Строки | java.lang | String |
"Продвинутые" числа | java.math | BigInteger и BigDecimal |
Дата и время | java.time | LocalDate, LocalTime, LocalDateTime, OffsetTime, OffsetDateTime, Instant |
Различные вариации даты и времени | java.util | Date и Calendar |
Старые форматы даты и времени | java.sql | Date, Time, Timestamp |
Массив байт или символов | byte[] или Byte[], char[] или Character[] | |
Перечисления (enum) | Любой enum | |
Сериализуемые объекты | Любая имплементация java.io.Serializable |
Для всех этих типов есть их аналоги в языке SQL, поэтому Hibernate хорошо знает, как их сохранять и загружать из базы.
Пример:
@Entity
@Table(name="user")
class User
{
@Column(name="id")
public Integer id;
@Column(name="name")
public String name;
@Column(name="level")
public Integer level;
@Column(name="created_date")
public Date createdDate;
}
Задания типа вручную – аннотация @Type
Иногда ты можешь захотеть вмешаться в политику Hibernate и явно указать ему в каком типе нужно хранить данные в базе. Например, у тебя в Entity-классе поле имеет тип Integer, но в базе для него есть колонка с типом VARCHAR.
Для этого есть специальная аннотация – @Type. Выглядит она очень просто:
@Type(type="имя-типа")
Давай, например, попросим Hibernate, чтобы поле createdDate нашего класса User хранилось в базе в виде строки:
@Entity
@Table(name="user")
class User
{
@Column(name="id")
public Integer id;
@Column(name="created_date")
@Type(type="org.hibernate.type.StringType")
public Date createdDate;
}
Если Hibernate поймет, как конвертировать тип Date в ваш новый тип, то просто сделает это. Если не поймет, тогда тебе нужно будет указать специальной конвертор типов. Но об этом немного позднее.
Список Hibernate-типов для баз данных
Кстати, ты обратил внимание, что мы указали тип org.hibernate.type.StringType, а не String. Это потому, что мы выбрали один из типов, который поддерживает СУБД, а не язык Java. У них у каждого своя система типов. Просто разработчики Hibernate придумали удобные названия в стиле Java, вместо этих VARCHAR’ов.
Кстати, этот список не такой уж и маленький. Приведу тут его часть:
Hibernate type (org.hibernate.type package) | JDBC type | Java type | BasicTypeRegistry key(s) |
---|---|---|---|
StringType | VARCHAR | java.lang.String | string, java.lang.String |
MaterializedClob | CLOB | java.lang.String | materialized_clob |
TextType | LONGVARCHAR | java.lang.String | text |
CharacterType | CHAR | char, java.lang.Character | char, java.lang.Character |
BooleanType | BIT | boolean, java.lang.Boolean | boolean, java.lang.Boolean |
NumericBooleanType | INTEGER, 0 is false, 1 is true | boolean, java.lang.Boolean | numeric_boolean |
YesNoType | CHAR, 'N'/'n' is false, 'Y'/'y' is true. The uppercase value is written to the database. | boolean, java.lang.Boolean | yes_no |
TrueFalseType | CHAR, 'F'/'f' is false, 'T'/'t' is true. The uppercase value is written to the database. | boolean, java.lang.Boolean | true_false |
ByteType | TINYINT | byte, java.lang.Byte | byte, java.lang.Byte |
ShortType | SMALLINT | short, java.lang.Short | short, java.lang.Short |
IntegerTypes | INTEGER | int, java.lang.Integer | int, java.lang.Integer |
LongType | BIGINT | long, java.lang.Long | long, java.lang.Long |
FloatType | FLOAT | float, java.lang.Float | float, java.lang.Float |
DoubleType | DOUBLE | double, java.lang.Double | double, java.lang.Double |
BigIntegerType | NUMERIC | java.math.BigInteger | big_integer, java.math.BigInteger |
BigDecimalType | NUMERIC | java.math.BigDecimal | big_decimal, java.math.bigDecimal |
TimestampType | TIMESTAMP | java.sql.Timestamp | timestamp, java.sql.Timestamp |
TimeType | TIME | java.sql.Time | time, java.sql.Time |
DateType | DATE | java.sql.Date | date, java.sql.Date |
CalendarType | TIMESTAMP | java.util.Calendar | calendar, java.util.Calendar |
CalendarDateType | DATE | java.util.Calendar | calendar_date |
CurrencyType | java.util.Currency | VARCHAR | currency, java.util.Currency |
LocaleType | VARCHAR | java.util.Locale | locale, java.utility.locale |
TimeZoneType | VARCHAR, using the TimeZone ID | java.util.TimeZone | timezone, java.util.TimeZone |
UrlType | VARCHAR | java.net.URL | url, java.net.URL |
ClassType | VARCHAR (class FQN) | java.lang.Class | class, java.lang.Class |
Таблица, конечно, большая, но очень полезная. Например, из нее понятно, что тип Boolean можно сохранить в базу как минимум шестью разными способами. Тебе столько не нужно? А кто сказал, что способ сохранения выбираешь ты?
В SQL нет типа Boolean и его часто хранят так:
- 1 или 0
- ‘F’ или ‘T’
- ‘Y’ или ‘N’
Поэтому очень хорошо, когда Hibernate понимает все эти заморочки. Или, например, давай возьмем хранение массивов данных в базе. Есть куча разных вариантов и Hibernate умеет работать с ними со всеми:
Hibernate type (org.hibernate.type package) | JDBC type | Java type | BasicTypeRegistr |
---|---|---|---|
BlobType | BLOB | java.sql.Blob | blog, java.sql.Blob |
ClobType | CLOB | java.sql.Clob | clob, java.sql.Clob |
BinaryType | VARBINARY | byte[] | binary, byte[] |
MaterializedBlobType | BLOB | byte[] | materized_blob |
ImageType | LONGVARBINARY | byte[] | image |
WrapperBinaryType | VARBINARY | java.lang.Byte[] | wrapper-binary, Byte[], java.lang.Byte[] |
CharArrayType | VARCHAR | char[] | characters, char[] |
CharacterArrayType | VARCHAR | java.lang.Character[] | wrapper-characters, Character[], java.lang.Character[] |
UUIDBinaryType | BINARY | java.util.UUID | uuid-binary, java.util.UUID |
UUIDCharType | CHAR, can also read VARCHAR | java.util.UUID | uuid-char |
PostgresUUIDType | PostgreSQL UUID, through Types#OTHER, which complies to the PostgreSQL JDBC driver definition | java.util.UUID | pg-uuid |
Hibernate type (org.hibernate.type package) | JDBC type | Java type | BasicTypeRegistr |
---|---|---|---|
DurationType | BIGINT | java.time.Duration | Duration, java.time.Duration |
InstantType | TIMESTAMP | java.time.Instant | Instant, java.time.Instant |
LocalDateTimeType | TIMESTAMP | java.time.LocalDateTime | LocalDateTime, java.time.LocalDateTime |
LocalDateType | DATE | java.time.LocalDate | LocalDate, java.time.LocalDate |
LocalTimeType | TIME | java.time.LocalTime | LocalTime, java.time.LocalTime |
OffsetDateTimeType | TIMESTAMP | java.time.OffsetDateTime | OffsetDateTime, java.time.OffsetDateTime |
OffsetTimeType | TIME | java.time.OffsetTime | OffsetTime, java.time.OffsetTime |
OffsetTimeType | TIMESTAMP | java.time.ZonedDateTime | ZonedDateTime, java.time.ZonedDateTime |
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ