sql2java — это легковесный генератор кода доступа к базе данных SQL (Java), который был переписан на основе одноимённого открытого проекта (https://sourceforge.net/projects/sql2java), работающего за рубежом. Этот ORM-инструмент запускается в виде плагина Maven и успешно протестирован на MySQL, а также применяется в реальных проектах.
Для компиляции требуется JDK 1.7 и версия Maven 3.5 или выше.
# Клонировать исходный код
git clone https://gitee.com/l0km/sql2java.git
cd sql2java
# Компилировать все
mvn install
```> SQL2Java-плагин Maven уже размещен в центральном репозитории Maven, поэтому если вам нужна только его запуск, нет необходимости компилировать этот проект.
## Быстрый справочник по использованию
### Создание конфигурационного файла
Создайте самый простой файл конфигурации (mysql2java.properties), чтобы указать sql2java, как следует генерировать Java-код. Символ '#' используется для начала строки-комментария.
```properties
# Указание JDBC-driver для соединения с базой данных
jdbc.driver=com.mysql.jdbc.Driver
# Для MySQL-базы данных, если useInformationSchema=false или не указано, то информация о полях таблиц не будет получена
jdbc.url=jdbc:mysql://localhost:3306/test?characterEncoding=utf8&useInformationSchema=true
jdbc.username=root
jdbc.password=
jdbc.schema=test
# Определение пакета для сгенерированного кода
codewriter.package=sql2java.test
Выполните следующий плагин Maven, чтобы начать чтение структуры таблиц из базы данных и сгенерировать соответствующие Java-классы в текущую директорию (src/main):
$ mvn com.gitee.l0km:sql2java-maven-plugin:generate \
-Dsql2java.classpath=lib/mysql-connector-java-5.1.43-bin.jar \
-Dsql2java.propfile=mysql2java.properties
``````text
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- sql2java-maven-plugin:1.0.6-SNAPSHOT:generate (default-cli) @ sql2java-test ---
Инициализация свойств базы данных
[INFO] classpath: [file:/D:/j/sql2java.test/lib/mysql-connector-java-5.1.43-bin.jar]
Подключение к root на jdbc:mysql://localhost:3306/test?characterEncoding=utf8&useInformationSchema=true...
Подключено.
Сервер базы данных: MySQL.
Загрузка списка таблиц в соответствии с шаблоном t_%...
Найдена таблица t_book
Найдена таблица t_user
samePrefix = [t_]
Загрузка столбцов...
t_book.id INT значение по умолчанию: null
t_book.name VARCHAR значение по умолчанию: null
t_book.borrower INT значение по умолчанию: null
t_book найдено 3 столбца
t_user.id INT AUTO_INCREMENT значение по умолчанию: null
t_user.name VARCHAR значение по умолчанию: null
t_user.birthdate DATE значение по умолчанию: null
t_user.phone VARCHAR значение по умолчанию: null
t_user.address VARCHAR значение по умолчанию: null
t_user найдено 5 столбцов
Database::loadPrimaryKeys
Найден первичный ключ (seq,name) (1,id) для таблицы 't_book'
Найден первичный ключ (seq,name) (1,id) для таблицы 't_user'
Загрузка импортированных ключей...
t_book.id -> t_user.id найдено seq:1 внешний ключ fk_id
UPDATE_RULE:NO_ACTION DELETE_RULE:RESTRICT
Загрузка индексов...
Найден интересующий индекс phone_UNIQUE на phone для таблицы t_user
Загрузка процедур...
Создание шаблона /templates/velocity/java5g/perschema/constant.java.vm
... запись в src/main/java/sql2java/test/Constant.java
java/sql2java/test/Constant.java завершено.
Создание шаблона /templates/velocity/java5g/perschema/database.properties
```vm
. . . запись в src/main/resources/conf/database.properties
resources/conf/database.properties завершена.
Создание шаблона /templates/velocity/java5g/perschema/gu.sql2java.irowmetadata.vm
. . . запись в src/main/resources/META-INF/services/gu.sql2java.IRowMetaData
resources/META-INF/services/gu.sql2java.IRowMetaData завершена.
Создание шаблона /templates/velocity/java5g/pertable/bean.java.vm
. . . запись в src/main/java/sql2java/test/BookBean.java
java/sql2java/test/BookBean.java завершена.
Создание шаблона /templates/velocity/java5g/pertable/manager.interface.java.vm
```запись в src/main/java/sql2java/test/IBookManager.java
java/sql2java/test/IBookManager.java завершена.
Генерация шаблона /templates/velocity/java5g/pertable/metadata.java.vm
. . . запись в src/main/java/sql2java/test/BookMetaData.java
java/sql2java/test/BookMetaData.java завершена.
Генерация шаблона /templates/velocity/java5g/pertable/bean.java.vm
. . . запись в src/main/java/sql2java/test/UserBean.java
java/sql2java/test/UserBean.java завершена.
Генерация шаблона /templates/velocity/java5g/pertable/manager.interface.java.vm
. . . запись в src/main/java/sql2java/test/IUserManager.java
java/sql2java/test/IUserManager.java завершена.
Генерация шаблона /templates/velocity/java5g/pertable/metadata.java.vm
. . . запись в src/main/java/sql2java/test/UserMetaData.java
java/sql2java/test/UserMetaData.java завершена.
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Общее время: 1.248 с
[INFO] Закончено в: 2019-12-16T13:51:20+08:00
[INFO] Конечная память: 13M/308M
[INFO] ------------------------------------------------------------------------l0km:sql2java-maven-plugin уже выпущен в центральный Maven-репозиторий, поэтому нет необходимости компилировать этот проект — его можно использовать сразу. В примерах выше версия плагина не указана, поэтому используется самая последняя версия плагина.
Параметры:| имя | описание |
| ------------------ | --------------------------------------------- |
| sql2java.classpath | Указывает путь к JAR-файлу JDBC-driver для подключения к базе данных |
| sql2java.propfile | Указывает конфигурационный файл, необходимый для генерации кода sql2java |
## Полный пример
См. демонстрационный проект sql2java: [sql2java-example: Пример вызова sql2java (gitee.com)](https://gitee.com/l0km/sql2java-example)
Пользователи могут использовать этот демонстрационный проект как основу для создания своего проекта ORM.
## Пример практического применения
См. открытый проект facelog: [https://gitee.com/l0km/facelog/tree/master/db2](https://gitee.com/l0km/facelog/tree/master/db2 "https://gitee.com/l0km/facelog/tree/master/db2")
## Получение всех параметров
Для управления способом генерации Java-кода, в Sql2Java используется несколько десятков контрольных параметров; большинство из которых по умолчанию не требуют изменения. Если требуется изменение этих параметров, необходимо получить их названия и описание. Для этого можно выполнить команду Maven плагина:
```bash
mvn com.gitee.l0km:sql2java-maven-plugin:help
Выполнение следующей команды Maven плагина создаст файл конфигурации с параметрами по умолчанию, который будет назван my.properties
. Вы можете использовать этот файл как основу для своих собственных настроек генерации кода:
mvn com.gitee.l0km:sql2java-maven-plugin:help -Dsql2java.output=my.properties
Пример вывода информации:```text [INFO] Scanning for projects... [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building sql2java test 1.0.2 [INFO] ------------------------------------------------------------------------ [INFO] [INFO] --- sql2java-maven-plugin:1.0.2:help (default-cli) @ sql2java-test --- [INFO] OUTPUT PROPERTIES TO J:\sql2java.test\my.properties [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 0.495 s [INFO] Finished at: 2019-11-20T15:25:27+08:00 [INFO] Final Memory: 10M/308M [INFO] ------------------------------------------------------------------------
## Описание параметров
Параметры конфигурации SQL2Java и их описание представлены ниже. Параметры задаются в виде `параметр_название = значение`, все строки начинающиеся с `#` являются комментариями.```properties
#______________________________________________
#
# (1/8) Конфигурация доступа к базе данных (обязательно)
#______________________________________________
# Класс JDBC-драйвера
#jdbc.driver=org.hsqldb.jdbcDriver
# URL доступа к базе данных
#jdbc.url=jdbc:hsqldb:hsql://localhost
# Логин пользователя базы данных
#jdbc.username=sa
# Пароль пользователя базы данных
#jdbc.password=
# Название базы данных
#jdbc.schema=null
#______________________________________________
#
# (2/8) Настройка метода получения автоинкрементных ключей (не обязательно)
#______________________________________________
# Эти параметры используются при вставке записей для получения значений автоинкрементных ключей
# Для JDBC версий bk 3.0 и выше, поддерживающих PreparedStatement.getGeneratedKeys(), эта секция не нужна
#
# Возможные значения для generatedkey.retrieve:
#
# auto - [по умолчанию] метод getGeneratedKeys автоматически получает ключи при использовании JDBC 3.0 драйвера.
#
# before - Получение значений автоинкрементных полей до вставки записи
#
# after - Получение значений автоинкрементных полей после вставки записи
#
# generatedkey.statement используется для определения SQL запроса получения значений автоинкрементных полей
# Если вы установите его значение в before или after, вам также потребуется настроить свойства
# generatedkey.statement
# <TABLE> плейсхолдер заменяет текущее имя таблицы
# <KEY> плейсхолдер заменяет текущее имя поля с автоинкрементом
#
#generatedkey.retrieve=auto
#generatedkey.statement=
#______________________________________________
#
# (3/8) Настройка генерации кода (необязательно)
#______________________________________________
codewriter.package=gu.sql2java.demo
codewriter.destdir=src/main
#codewriter.destdir.extension=
#codewriter.package.extension=
#general.beanconverter.tonative.ignore=create_time,update_time
#swift.annotation.bean=true
#swagger.annotation.bean=true
codewriter.bean.primitiveSetter=true
codewriter.bean.dateLongSetter=true
codewriter.bean.dateSerializeType=Long
codewriter.bean.dateStringFormat=yyyy-MM-dd'T'HH:mm:ss.SSSZ
bitstate.type=int
#binary.type=byte[]
#json.jackson.rawvalue=false
database.properties.env=config_folder database.
database.properties.dir=resources/conf
database.properties=database.properties
# Флаг совместимости с axis2
#bean. compatible_axis2=true
#Файл свойств для инициализации Velocity
#codewriter. velocityprops=somefile
#Путь загрузки шаблонов по умолчанию (не менять)
velocity. templates. loadingpath=/templates/velocity/includes
#Путь загрузки вложенных шаблонов для каждой таблицы и каждого схемы (не менять)
velocity. templates=/templates/velocity/
############ Расширенные шаблоны ###############
#Пользователи могут указать путь к расширенным шаблонам (.vm) через следующие параметры
#sql2java генератор будет использовать эти параметры для выполнения расширенных шаблонов
#Путь загрузки расширенных шаблонов
#velocity. templates. loadingpath. extension=
#Путь загрузки расширенных шаблонов для каждой таблицы и каждого схемы
#velocity. templates. extension =
#Устанавливает префикс для всех сгенерированных классов
#полезно, если вы беспокоитесь о коллизиях пространства имён с зарезервированными словами
#или классами java.lang
codewriter. classprefix=
#Создание значений по умолчанию для полей
codewriter. generate. defaultvalue=true
#______________________________________________
#(4/8) Настройка фильтрации таблиц и шаблонов (опционально)
#______________________________________________
#Фильтрация по типу таблицы
#Для указания типа таблиц, для которых требуется создание кода (список типов таблиц, разделённых запятыми)
#Типы таблиц определяются как: TABLE, VIEW, SYSTEM TABLE, SYNONYM
jdbc. tabletypes=TABLE, VIEW
#Фильтрация по имени таблицы
#Использует маску % для фильтрации имен таблиц, для которых требуется создание кода# Вы можете указать список масок, разделённых запятыми
# Например, %_name, ul_% создаст код только для таблиц с суффиксом _name или префиксом ul_
# По умолчанию создаётся код для всех таблиц в схеме
jdbc.tablenamepattern=%
# Белый список / чёрный список имен таблиц (этот функционал ещё не активирован)
# Белый список
# Список имен таблиц, разделённых пробелами, для которых будет создан код
# Чёрный список
# Список имен таблиц, разделённых пробелами, для которых не будет создан код
# Можно указать либо белый список, либо чёрный список, но не оба одновременно
# Белый список
tables.include=
# Чёрный список
tables.exclude=
# Белый список каталогов шаблонов
# Белый список
# Список разделенных пробелами имён таблиц, только те шаблоны в папках, чьи названия находятся в этом списке, будут генерироваться
# Чёрный список
# Список разделенных пробелами имён таблиц, шаблоны в папках с такими названиями не будут генерироваться
# Можно указать либо белый, либо чёрный список, если указаны оба — игнорируется чёрный список
template.folder.exclude=
template.folder.include=java5g
# java5g : общие шаблоны бинов и менеджеров для Java5
# (6/8) ЧТО ДОЛЖНО БЫТЬ ВИДНО/НЕ ВИДНО НА КЛИЕНТЕ?
# пустое значение означает все поля
#______________________________________________
# Список полей, доступных только локально, разделенный запятыми
# Список имен полей в определенной таблице, доступных только локально# Эквивалент определению в аннотации поля: 'SCOPE@LOCAL@EPOSC'
# Пример:
# table.user_info.scope.local=private_time,password
# Список полей, видимых LOCAL, разделенный запятыми
# Список имен полей в определенной таблице, доступных через локальный вызов
# Эквивалент определению в аннотации поля: 'SCOPE@THRIFT@EPOSC'
# Пример:
# table.user_info.scope.thrift=password
# Список полей, видимых THRIFT, разделенный запятыми
# Список имен полей в определенной таблице, доступных через RPC
# Эквивалент определению в аннотации поля: 'SCOPE@JSON@EPOSC'
# Пример:
# table.user_info.scope.json=private_time,password
# Список полей, видимых JSON, разделенный запятыми
# Список имен полей в определенной таблице, доступных для сериализации JSON#______________________________________________
#
# (7/8) Конфигурация типов JDBC (необязательно)
#______________________________________________
#
# Преобразование типа DATE JDBC в тип Java, возможные значения:
# java.sql.Date
# java.util.Date
jdbc2java.date=java.util.Date
# Преобразование типа TIME JDBC в тип Java, возможные значения:
# java.sql.Time
# java.util.Date
jdbc2java.time=java.util.Date
# Преобразование типа TIMESTAMP JDBC в тип Java, возможные значения:
# java.sql.Timestamp
# java.util.Date
jdbc2java.timestamp=java.util.Date
#______________________________________________
#
# (8/8) Конфигурация оптимистической блокировки (необязательно)
#______________________________________________
# optimisticlock.type имеет два возможных значения:
## none — механизм оптимистичной блокировки не активирован (по умолчанию).
#
# timestamp — поле оптимистичной блокировки содержит значение System.currentTimeMillis().
#
# optimisticlock.column определяет имя поля оптимистичной блокировки; если это имя отсутствует, механизм оптимистичной блокировки не будет активирован.
# тип поля оптимистичной блокировки может быть java.lang.Long или java.lang.String.
optimisticlock.type = timestamp
optimisticlock.column = version_time## Декодеры и кодеры столбцов базы данных
С версии 3.21.0 sql2java добавил интерфейс [ColumnCodec](sql2java-base/src/main/java/gu/sql2java/BaseColumnCodec.java) для применения слоев пользовательской сериализации и десериализации данных в столбцах таблиц. Метод сериализации (`ColumnCodec.serialize`) используется для преобразования пользовательских типов данных в типы хранения в базе данных, а метод десериализации (`ColumnCodec.deserialize`) — для обратного преобразования. Поддержка типа JSON реализуется с помощью [JsonColumnCodec](sql2java-base/src/main/java/gu/sql2java/json/JsonColumnCodec.java); приложения могут использовать этот декодер как пример для создания своих пользовательских декодеров и кодеров столбцов.## Поддержка пользовательских типов полей
С версии 3.21.0 sql2java добавил метки аннотаций `ANNOTATION` и `TYPE`. Приложение определяет типы полей и кодеры/декодеры для этих полей, а sql2java автоматически генерирует Java-поля и аннотацию `@ColumnCodecConfig` на основе этих меток.
### TYPE
Определяет тип поля, например `TYPE@net.facelib.eam.interpreter.Rectangle@EPYT` определяет тип поля как `net.facelib.eam.interpreter.Rectangle`.
### ANNOTATION
Определяет аннотации для поля, можно указывать несколько аннотаций, например `ANNOTATION@gu.sql2java.annotations.ColumnCodecConfig(net.facelib.eam.interpreter.sql2java.EamPlayColumnCodec.class)@NNAA` создаст аннотацию `@gu.sql2java.annotations.ColumnCodecConfig(net.facelib.eam.interpreter.sql2java.EamPlayColumnCodec.class)` для Java-поля.### Пример
В следующей таблице поле `rect` определяется через `TYPE@@EPYT` и `ANN@@NNA`.
```sql
CREATE TABLE IF NOT EXISTS dc_device_channel (
`device_id` int NOT NULL COMMENT 'X@NAME: Устройство ID@X',
`sid` int NOT NULL DEFAULT 0 COMMENT 'X@NAME: Физический экран ID@x',
`area` varchar(32) NOT NULL COMMENT 'X@NAME: Область отображения ID@x',
`rect` varchar(256) DEFAULT NULL COMMENT 'ANN@gu.sql2java.annotations.ColumnCodecConfig(net.facelib.eam.interpreter.sql2java.EamPlayColumnCodec.class)@NNATYPE@net.facelib.eam.interpreter.Rectangle@EPYT'
)
```eam. interpreter. Rectangle@EPYTX@Имя: Координаты области отображения@x, соответствует синтаксису defineChannel в EamPlayer',
`канал` varchar(32) NOT NULL COMMENT 'X@NAME: Канал ID@x, область отображения, связанная с этим каналом',
`run_задачи` text DEFAULT NULL COMMENT 'X@NAME: Задачи воспроизведения@X описание, описание задач воспроизведения, которое записывается устройством, соответствует методам definePlanTask и defineTrigger в EamPlayer',
PRIMARY KEY (`device_id`, `sid`, `область`),
FOREIGN KEY (device_id) REFERENCES dc_device(id) ON DELETE CASCADE,
INDEX (канал)
) COMMENT 'X@NAME: Записи канала области отображения устройства@X' DEFAULT CHARSET=utf8;
rect
/** комментарий: X@NAME: Координаты области отображения@x, соответствует синтаксису defineChannel в EamPlayer */
@ApiModelProperty(value = "X@NAME: Координаты области отображения@x, соответствует синтаксису defineChannel в EamPlayer", dataType = "Rectangle")
@CodegenLength(max = 256) @CodegenInvalidValue
@ExcelColumn(sort = 4)
@gu.sql2java.annotations.ColumnCodecConfig(net.facelib.eam.interpreter.sql2java.EamPlayColumnCodec.class)
private net.facelib.eam.interpreter.Rectangle rect;
```#### Получатель/Установщик методы для типа `net.facelib.eam.interpreter.Rectangle`
##### Получатель метод
```java
@ThriftField(value = 7)
@JsonProperty("rect")
public net.facelib.eam.interpreter.Rectangle getRect() {
return rect;
}
@ThriftField(name = "rect")
@JsonProperty("rect")
public void setRect(net.facelib.eam.interpreter.Rectangle newVal) {
modified |= DC_DEVICE_CHANNEL_ID_RECT_MASK;
initialized |= DC_DEVICE_CHANNEL_ID_RECT_MASK;
if (Objects.equals(newVal, rect)) {
return;
}
rect = newVal;
}
rect
public String readRect() {
return metaData.columnCodecs[DC_DEVICE_CHANNEL_ID_RECT].serialize(rect, String.class);
}
public void writeRect(String newVal) {
modified |= DC_DEVICE_CHANNEL_ID_RECT_MASK;
initialized |= DC_DEVICE_CHANNEL_ID_RECT_MASK;
rect = metaData.columnCodecs[DC_DEVICE_CHANNEL_ID_RECT].deserialize(newVal, metaData.fieldOf(DC_DEVICE_CHANNEL_ID_RECT).getGenericType());
}
Поле SCOPE@@EPOSC
используется для определения видимости поля, его формат следующий:
SCOPE@(LOCAL|JSON|THRIFT)@EPOSC
Он позволяет определить три уровня видимости:
Пример ниже показывает таблицу с определением столбца private_time
, где используется метка SCOPE@@EPOSC
. Это указывает на то, что поле доступно только локально, то есть только сам сервис может читать и писать в это поле.sql CREATE TABLE IF NOT EXISTS dc_device ( `id` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT 'X@NAME:ID устройства@X', `name` varchar(32) DEFAULT NULL COMMENT 'X@NAME:Название устройства@X, указано пользователем', `physical_address` varchar(32) NOT NULL UNIQUE COMMENT 'X@NAME:Физический адрес@X, MAC-адрес, IMEI или другой уникальный идентификатор устройства', `private_time` bigint DEFAULT 0 COMMENT 'SCOPE@LOCAL@EPOSC Временная метка создания токена устройства (миллисекунды), этот столбец будет обновлен каждый раз при создании токена устройства', `os_arch` varchar(64) DEFAULT NULL COMMENT 'X@NAME:Архитектура ОС@X, название операционной системы и версия, а также имя аппаратной архитектуры, например: Windows-x86_64, Linux-x86_64, Android-arm...' ) COMMENT 'X@NAME:Запись устройств для фронтенда@X, основная информация об устройствах для фронтенда' DEFAULT CHARSET=utf8;
Класс DeviceBean
, сгенерированный sql2java-generator
, содержит поле privateTime
, которое соответствует столбцу private_time
таблицы dc_device
. Код определения этого поля представлен ниже:
/**
* Комментарий: временная метка создания токена устройства (миллисекунды). Этот столбец будет обновлен каждый раз при создании токена устройства.
*/
@ApiModelProperty(value = "временная метка создания токена устройства (миллисекунды). Этот столбец будет обновлен каждый раз при создании токена устройства.", dataType = "Long")
@CodegenDefaultvalue("0") @CodegenInvalidValue("-1")
@ExcelColumn(sort = 9)
@JsonField(serialize = false, deserialize = false)
@JsonIgnore
private Long privateTime;
/**
* Метод получения значения поля {@link #privateTime}.
*
* Информация метаданных (в процессе):
* <ul>
* <li>полное имя: dc_device.private_time</li>
* <li>комментарий: временная метка создания токена устройства (миллисекунды). Этот столбец будет обновлен каждый раз при создании токена устройства.</li>
* <li>значение по умолчанию: '0'</li>
* <li>размер колонки: 19</li>
* <li>тип данных JDBC, возвращаемый драйвером: Types.BIGINT</li>
* </ul>
*
* @return значение поля privateTime
*/
@JsonIgnore
public Long getPrivateTime() {
Можно заметить, что член privateTime
имеет Jackson аннотацию @JsonIgnore
и FastJson аннотацию @JSONField
, указывающие на то, что это поле должно игнорироваться при сериализации и десериализации в JSON. В то же время метод getter для privateTime
также не имеет аннотации Thrift @ThriftField
, что означает, что это поле не было определено как член Thrift.Плагин swift2thrift-maven-plugin
не будет содержать поля privateTime
в сгенерированном IDL:
struct DeviceBean {
1: required bool _new;
2: required i32 modified;
3: required i32 initialized;
4: optional i32 id;
5: optional string name;
6: optional string physicalAddress;
7: optional string osArch;
}
3.19.0 версия и выше позволяют более детально определять типы данных для целочисленных полей, таких как TINYINT
, SMALLINT
, INT
. Пример таблицы:
SQL Тип | Java Поле Тип | Описание |
---|---|---|
TINYINT/BOOL/BOOLEAN |
Byte /Boolean
|
Если базовый комментарий поля (COMMENT ) содержит [NUM,Boolean] , генерируемое поле Java будет типа Boolean , в противном случае — Byte
|
SMALLINT | Short |
|
INT | Integer |
Пример:
CREATE TABLE IF NOT EXISTS dc_device (
id int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT 'Уникальный идентификатор устройства',
online boolean DEFAULT false COMMENT '[NUM,Boolean], метка онлайн'
);
Согласно вышеприведенному определению, если поле типа boolean/bool
или TINYINT
имеет комментарий [NUM,Boolean]
, то в сгенерированном Java Bean поле online
будет иметь тип Boolean
.
Внимание: Маркер
[NUM,Boolean]
должен находиться в начале строки комментария.
С версии 3.8, sql2java поддерживает автоматическую сериализацию и десериализацию строковых полей, содержащих JSON данные.### Включение json.jackson.rawvalue
Для активации этой возможности требуется выполнение следующих двух шагов:
Генерируемый при этом код требует наличия библиотек fastjson и jackson.
sql2java.properties
.
Установите значение json.jackson.rawvalue
равным true
, добавив следующую строку:```properties#json.jackson.rawvalue = true
- Изменение DDL-запроса на создание таблицы
В комментариях к полям, предназначенным для хранения данных в формате JSON, добавьте префикс [JSON_STR,...]. Этот префикс указывает, что поле предназначено для хранения данных в формате JSON (только для полей типа String).
Пример:
```sql
CREATE TABLE IF NOT EXISTS dc_device_group (
`id` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT 'ID группы устройств',
`name` varchar(32) NOT NULL COMMENT 'Название группы устройств',
`address` varchar(128) DEFAULT NULL COMMENT 'Адрес группы устройств: район/улица/номер дома',
`props` text DEFAULT NULL COMMENT '[JSON_STR,obj] Расширенные поля в формате JSON (максимальный размер bcm 64КБ), используемые для определения расширений информации, online_time: время включения, offline_time: время выключения, close_time: время закрытия станции, operator: оператор',
`create_time` timestamp DEFAULT CURRENT_TIMESTAMP,
`update_time` timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) COMMENT 'Информация о группах устройств' DEFAULT CHARSET=utf8;
```
В приведённом выше примере комментарий к полю `props` начинается с `[JSON_STR,obj]`, что указывает на то, что это поле является полем JSON, тип которого Object.
После выполнения этих двух шагов достаточно просто перезапустить процесс Sql2java для генерации нового кода.
```### [JSON_STR]
При генерации кода будет использоваться префикс `[JSON_STR,...]` для определения типа поля JSON.
| Формат [JSON_STR] | Тип поля JSON |
|-------------------------------------------|-------------------------------|
| [JSON_STR,array] | com.alibaba.fastjson.JSONArray |
| [JSON_STR,object] | com.alibaba.fastjson.JSONObject |
| [JSON_STR,obj] | com.alibaba.fastjson.JSONObject |
| [JSON_STR] | com.alibaba.fastjson.JSON |
| [JSON_STR,com.mycompany.product.User] | com.mycompany.product.User |
### Пример генерируемого кода
Код определения поля `props`:
```java
/** Комментарий: [JSON_STR] Расширенные поля в формате JSON (максимальный размер 64 КБ), используемые для определения расширений информации, online_time: время включения, offline_time: время выключения, close_time: время закрытия станции, operator: оператор */
@ApiModelProperty(value = "[JSON_STR] Расширенные поля в формате JSON (максимальный размер 64 КБ), используемые для определения расширений информации, online_time: время включения, offline_time: время выключения, close_time: время закрытия станции, operator: оператор", dataType = "String")
@CodegenLength(max = 65535)
@CodegenInvalidValue
@JsonRawValue
@com.fasterxml.jackson.databind.annotation.JsonSerialize
@JsonDeserialize(using = gu.sql2java.json.RawJsonDeserializer.class)
private com.alibaba.fastjson.JSONObject props;
@ThriftField(value = 16)
@JsonProperty("props")
public String getProps() {
return null == props ? null : props.toJSONString();
}
@ThriftField(name = "props")
@JsonProperty("props")
public void setProps(String newVal) {
modified |= DC_DEVICE_GROUP_ID_PROPS_MASK;
initialized |= DC_DEVICE_GROUP_ID_PROPS_MASK;
props = com.alibaba.fastjson.JSONObject.parseObject(newVal, com.alibaba.fastjson.JSONObject.class);
}
```### Дополнительно сгенерированные методы для прямого чтения/записи JSON объекта:
```java
/**
* Метод чтения для {@link #props}.
*/
public com.alibaba.fastjson.JSONObject readProps() {
return props;
}
/**
* Метод записи для {@link #props}, использует JSON объект.
*/
public void writeProps(com.alibaba.fastjson.JSONObject newVal) {
modified |= DC_DEVICE_GROUP_ID_PROPS_MASK;
initialized |= DC_DEVICE_GROUP_ID_PROPS_MASK;
if (Objects.equals(newVal, props)) {
return;
}
props = newVal;
}
{
"modified": 0,
"initialized": 65535,
"new": false,
"id": 5,
"name": "Лянпинь гоудун цзутан",
"address": null,
"props": {
"offline_time": "22:00",
"online_time": "8:00",
"operator": "неизвестен"
},
"createTime": "2022-07-06T12:41:56.000+0800",
"updateTime": "2022-07-06T12:41:56.000+0800"
}
С версии 3.10, sql2java предоставляет возможность экспорта данных записей в поток или файл Excel-формата, реализованное на основе apache/poi. Подробнее см. sql2java-excel/README.md.
Функционал sql2java-excel позволяет конфигурировать каждое поле таблицы через аннотации для экспорта в Excel. Генератор sql2java-generator поддерживает создание аннотаций @ExcelSheet и @ExcelColumn в Java Bean классах на основании зарезервированных меток в SQL-таблицах и полях.
Для включения генерации аннотаций Excel требуется выполнить следующие два шага:> Для активации этой функции необходима поддержка библиотеки sql2java-excel.
excel.annotation.bean
равным true
. Пример конфигурации:# Генерация аннотаций @ExcelSheet и @ExcelColumn при значении true
excel.annotation.bean = true
X@...@X
:sql CREATE TABLE IF NOT EXISTS dc_device ( `id` INT(11) NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT 'X@NAME:Уникальный идентификатор устройства@X', `group_id` INT(11) DEFAULT 1 COMMENT 'X@NAME:Идентификатор группы устройств@X', `features` INT(11) DEFAULT 0 COMMENT 'X@NAME:Флаги характеристик группы устройств@X, определяются уровнем приложения', `name` VARCHAR(32) DEFAULT NULL COMMENT 'X@NAME:Название устройства@X, указанное пользователем', `physical_address` VARCHAR(32) NOT NULL UNIQUE COMMENT 'Устройство X@NAME:Физический адрес@X, MAC-адрес, IMEI или другой уникальный идентификатор устройства', `address_type`VARCHAR(16) NOT NULL DEFAULT 'MAC' COMMENT 'Устройство физический X@NAME:Тип адреса@X (MAC, IMEI и т. д.), по умолчанию шестизначный MAC-адрес (HEX)', `iot_card` VARCHAR(32) DEFAULT NULL UNIQUE COMMENT 'Устройство X@NAME:Номер SIM-карты IoT@X, например ICCID для China Unicom', `status` VARCHAR(32) NOT NULL DEFAULT 'ENABLE' COMMENT 'X@NAME:Статус устройства@X, X@VALUES:ENABLE: нормальный, DISABLE: отключен, MAINTAIN: обслуживание, PENDING: подтвержден (ожидает проверки)@X', `private_time` BIGINT DEFAULT 0 COMMENT 'Устройство X@NAME:Временная метка создания токена@X, обновляется каждый раз при создании нового токена устройства', `screen_info` VARCHAR(32) DEFAULT NULL COMMENT 'X@NAME:Информация о экране устройства@X, пример формата: 15H1080x960 -- 15 (дюймов) горизонтальное разрешение 1080x960, 21V960x1080 -- 21 (дюймов) вертикальное разрешение 960x1080', `fixed_mode` VARCHAR(8) DEFAULT 'FLOOR' COMMENT 'Устройство X@NAME:Режим установки@X, X@VALUES:HANG: подвесной, FLOOR: напольный@X' );
os_arch
varchar(64) DEFAULT NULL COMMENT 'X@NAME:Операционная система и архитектура@X: название ОС и версия, а также архитектура оборудования, например Windows-x86_64, Linux-x86_64, Android-arm и т. д.',
network
varchar(32) DEFAULT NULL COMMENT 'X@NAME:Тип соединения сети@X: 4G, WIFI, ETHERNET'
) `version_info` varchar(32) DEFAULT NULL COMMENT 'версия приложения на устройстве, формат определяется уровнем приложений',
`model` varchar(32) DEFAULT NULL COMMENT 'модель устройства',
`vendor` varchar(32) DEFAULT NULL COMMENT 'поставщик устройства',
`device_detail` varchar(512) DEFAULT NULL COMMENT '[JSON_STR,obj] детали продукта устройства в формате JSON, JSON поля: X@NAMES:device_name: название продукта, manufacturer: производитель, made_date: дата производства@X, уровень приложений может расширяться по необходимости',
`props` text DEFAULT NULL COMMENT '[JSON_STR,obj] расширенные поля в формате JSON (максимальный размер 64КБ), используемые для определения дополнительной информации, X@NAMES:last_active_time: последнее время активности, disk_capacity: объём жесткого диска, status_comment: комментарий изменения состояния@X',
`plan_id` varchar(64) DEFAULT NULL COMMENT 'текущий ID программы',
`target_id` varchar(64) DEFAULT NULL COMMENT 'целевой ID программы',
`remark` varchar(256) DEFAULT NULL COMMENT 'замечание',
`create_time` timestamp DEFAULT CURRENT_TIMESTAMP COMMENT 'время создания записи',
`update_time` timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'время обновления записи'
) COMMENT 'запись оборудования переднего плана, основная информация об оборудовании переднего плана, X@SHEET:titleFillColor=YELLOW,hideColumns=private_time|props|device_detail@X' DEFAULT CHARSET=utf8;
```С этими метками, sql2java-generator сгенерирует следующий Java Bean код с специальными аннотациями `@ExcelSheet`, `@ExcelColumn`:```java
/**
* DeviceBean представляет собой отображение таблицы dc_device.
* <br>Метаданные (в процессе):
* <ul>
* <li>описание: запись оборудования переднего плана, основная информация об оборудовании переднего плана,</li>
* </ul>
* @author guyadong
*/
@ExcelSheet(sheetName="dc_device",title="запись оборудования переднего плана",titleFillColor="YELLOW",hideColumns={"private_time","props","device_detail"})
public final class DeviceBean extends BaseRow
implements Serializable, Constant
{
private static final long serialVersionUID = -3495281739409382636L;
/** описание: идентификатор устройства */
@ExcelColumn(sort=1,name="идентификатор устройства")
private Integer id;
/** описание: идентификатор группы устройства */
@ExcelColumn(sort=2,name="идентификатор группы устройства")
private Integer groupId;
/** описание: характеристики группы устройств, определенные уровнем приложений */
@ExcelColumn(sort=3,name="характеристики группы устройств")
private Integer features;
/** описание: имя устройства, указанное пользователем */
@ExcelColumn(sort=4,name="имя устройства")
private String name;
/** комментарий: физический адрес устройства, MAC адрес, IMEI или другой идентификатор устройства */
@ExcelColumn(sort=5,name="физический адрес")
private String physicalAddress;
/** комментарий: тип физического адреса устройства (MAC, IMEI и т. д.), по умолчанию шестизначный MAC адрес (HEX) */
@ExcelColumn(sort=6,name="тип адреса")
private String addressType;
/** комментарий: номер SIM-карты IoT устройства, например, для China Unicom это ICCID */
@ExcelColumn(sort=7,name="номер SIM-карты IoT")
private String iotCard;
}
``` /** комментарий: состояние устройства, ENABLE: нормальное, DISABLE: отключено, MAINTAIN: обслуживание, PENDING: приостановлено (ожидает проверки) */
@ExcelColumn(sort = 8, name = "Состояние устройства", readConverterExp = "ENABLE=нормальное, DISABLE=отключено, MAINTAIN=обслуживание, PENDING=приостановлено (ожидает проверки)")
private String status;
/** комментарий: время создания токена устройства в миллисекундах, каждое время создания токена устройства это поле обновляется */
@ExcelColumn(sort = 9)
private Long privateTime;
/** комментарий: информация о экране устройства, пример формата: 15H1080x960 -- 15 (дюймов) горизонтальный экран с разрешением 1080x960, 21V960x1080 -- 21 (дюймов) вертикальный экран с разрешением 960x1080 */
@ExcelColumn(sort = 10, name = "Информация о экране устройства")
private String screenInfo;
/** комментарий: метод установки, HANG: подвесной, FLOOR: напольный */
@ExcelColumn(sort = 11, name = "Метод установки", readConverterExp = "HANG=подвесной, FLOOR=напольный")
private String fixedMode;
/** комментарий: платформа операционной системы, название и версия ОС и архитектура оборудования, например: Windows-x86_64, Linux-x86_64, Android-arm и т. д. */
@ExcelColumn(sort = 12, name = "Платформа операционной системы")
private String osArch;
/** комментарий: тип соединения сети: 4G, WIFI, ETHERNET */
@ExcelColumn(sort = 13, name = "Тип соединения сети")
private String network;
/** комментарий: версия программного обеспечения на устройстве, формат определяется уровнем приложения */
@ExcelColumn(sort = 14, name = "Версия")
private String versionInfo;
/** комментарий: модель устройства */```java
@ExcelColumn(sort=15,name="Device Model")
private String model;
/** comment: device provider */
@ExcelColumn(sort=16,name="Device Vendor")
private String vendor;
/** comment: detailed information about the device product defined in JSON format, JSON fields: device_name: product name, manufacturer: producer, made_date: production date, application level can be extended as needed */
@ExcelColumns({
@ExcelColumn(sort=17,name="Detailed Information About Device Product"),
```
```markdown
### EXCEL метки
Этот раздел объясняет, как определяются метки EXCEL `X@...@X`.
```#### MARKER NAME
`X@NAME:xxxx@X` — это метка определения имени таблицы/поля, которая используется для определения названий столбцов или заголовков в экспортированном Excel-файле. Когда она встречается в комментариях к таблице (COMMENT), то соответствует полю `title` аннотации `@ExcelSheet`. В случае комментариев к полям (COMMENT) она соответствует полю `name` аннотации `@ExcelColumn`.
#### MARKER NAMES
```
`X@NAMES:a=b,c=d@X` является маркером многосимвольной определенной метки, который определяет таблицу или поле в выходных данных EXCEL как имя столбца для членов или подчленов. Когда он встречается в комментариях к таблице (COMMENT), он соответствует аннотации `@ExcelColumn`, которая определяет имя столбца для членов или подчленов таблицы.
В приведенном выше примере поле `device_detail` определено как JSON объектное поле, а в комментариях указан тэг NAMES: `X@NAMES:device_name: продукт, manufacturer: производитель, made_date: дата производства @X`. Это определяет подчлены поля JSON `device_name`, `manufacturer`, `made_date` и соответствующие им названия колонок при экспорте в EXCEL.
> Если фактическое JSON поле содержит больше трёх полей, таких как поле `location`, которое не было определено, то как будет называться колонка этого поля? По умолчанию это будет `location`.
```#### ТЭГ VALUES
`X@VALUES:a=b,c=d@X` является маркером многозначного преобразования, используемым для определения содержимого значений полей при экспорте в Excel. Соответствует параметру `readConverterExp` аннотации `@ExcelColumn`.Как показано в примере, поле `dc_device.status` определяет тэг VALUES: `X@VALUES:ENABLE: нормальный, CLOSED: закрытый, MAINTAIN: обслуживание, PENDING: ожидающий (ожидание проверки) @X`. То есть, когда значение поля `status` равно `ENABLE`, значение в Excel будет `нормальный`, и так далее.
#### ТЭГ COLUMN
`X@COLUMN:name=a,b=c,d=e@X` является маркером полного определения аннотации `@ExcelColumn`, где аннотация `@ExcelColumn` имеет десятки конфигурируемых параметров. Параметры `name, readConverterExp` являются наиболее распространенными, поэтому используются специальные тэги NAME и VALUES. Для других параметров можно использовать тэг COLUMN.
#### ТЭГ SHEET
`X@SHEET:name=a,b=c,d=e@X` является маркером полного определения аннотации `@ExcelSheet`, где аннотация `@ExcelSheet` также имеет десятки конфигурируемых параметров. Параметр `name` является наиболее распространенным, поэтому используется специальный тэг NAME. Для других параметров можно использовать тэг SHEET.
Пример использования тэга SHEET в комментариях к таблице `dc_device`: `X@SHEET:titleFillColor=YELLOW, hideColumns=private_time|props|device_detail@X`
> Обратите внимание, что тип параметра `hideColumns` аннотации `@ExcelSheet` — это массив строк, поэтому при использовании тэга SHEET для определения нескольких элементов массива разделите их символом `|`.#### Принципы специальных маркеров
Специальные маркеры имеют приоритет над общими маркерами COLUMN и SHEET. Если для поля используется COLUMN тег, где указано `name`, а также используется NAME тег для указания имени столбца, в этом случае приоритет имеет значение, указанное с помощью NAME тега. Для SHEET тега логика такая же.## Поддержка полей типа Geometry
```sql
CREATE TABLE dc_spot (
`id` INT(11) PRIMARY KEY AUTO_INCREMENT,
`name` VARCHAR(255) DEFAULT NULL COMMENT 'Название места',
`spot` POINT DEFAULT NULL COMMENT 'Точка координат'
) ENGINE = MyISAM DEFAULT CHARSET = utf8;
```
С версии 3.18.0 поддерживаются все пространственные типы данных MySQL (выше 5.7) ([Пространственные типы данных](https://dev.mysql.com/doc/refman/5.7/en/spatial-type-overview.html)), то есть поля типа Geometry автоматически генерируют члены типа `com.vividsolutions.jts.geom.Geometry`.
Далее представлено соответствие между названиями пространственных типов данных MySQL и объектами геометрии JTS:
| Название пространственного типа данных MySQL | Класс JTS |
|-------------------|----------------------------------------------|
| GEOMETRY | com.vividsolutions.jts.geom.Geometry |
| POINT | com.vividsolutions.jts.geom.Point |
| LINESTRING | com.vividsolutions.jts.geom.LineString |
| POLYGON | com.vividsolutions.jts.geom.Polygon |
| MULTIPOINT | com.vividsolutions.jts.geom.GeometryCollection |
| MULTILINESTRING | com.vividsolutions.jts.geom.GeometryCollection |
| MULTIPOLYGON | com.vividsolutions.jts.geom.GeometryCollection |
| GEOMETRYCOLLECTION | com.vividsolutions.jts.geom.GeometryCollection |
### Настройки параметров
Чтобы контролировать типы getter/setter методов для полей типа Geometry в сгенерированном коде, был добавлен параметр `codewrite.bean.geometry.serial.type`.
Описание параметра `codewrite.bean.geometry.serial.type`:- STRING
**[Значение по умолчанию]** Когда `codewrite.bean.geometry.serial.type=STRING`, типы getter/setter методов для полей типа Geometry являются String, то есть геометрические объекты представляются как WKT строки.
Поскольку String является простым типом, этот способ хорошо читаемый и универсальный, что соответствует обычному подходу к работе с типом Geometry.
Пример сгенерированного кода:
```java
private com.vividsolutions.jts.geom.Point spot;
/** Преобразование spot в WKT строку */
public String getSpot() {
return null == spot ? null : spot.toText();
}
/** Преобразование WKT строки в Point и сохранение его в spot */
public void setSpot(String newVal) {
spot = (null == newVal || newVal.isEmpty()) ? null : GeometryDataCodec.DEFAULT_INSTANCE.fromWKTUnchecked(newVal, Point.class);
}
/** Возвращает оригинальный объект spot */
public com.vividsolutions.jts.geom.Point readSpot() {
return spot;
}
```
Внимание: Оставшаяся часть примера кода была прервана и не завершена.```java
public void setSpot(String newVal){
spot = (null == newVal || newVal.isEmpty()) ? null : GeometryDataCodec.DEFAULT_INSTANCE.fromWKTUnchecked(newVal, Point.class);
}
/** Возвращает оригинальный объект spot */
public com.vividsolutions.jts.geom.Point readSpot(){
return spot;
}```markdown
- JTS
Когда `codewrite.bean.geometry.serial.type=JTS`, используется JTS Geomertry тип непосредственно в методах getter/setter для полей типа Geometry.
Пример сгенерированного кода:
```java
@com.fasterxml.jackson.databind.annotation.JsonDeserialize(using = gu.sql2java.geometry.jackson.GeometryDeserializer.class)
@com.fasterxml.jackson.databind.annotation.JsonSerialize(using = gu.sql2java.geometry.jackson.GeometrySerializer.class)
@com.alibaba.fastjson.annotation.JSONField(serializeUsing=gu.sql2java.geometry.fastjson.PointCodec.class,deserializeUsing=gu.sql2java.geometry.fastjson.PointCodec.class)
private com.vividsolutions.jts.geom.Point spot;
/** Возвращает оригинальный объект sport */
public com.vividsolutions.jts.geom.Point getSpot(){
return spot;
}
/** Изменяет оригинальный объект sport */
public void writeSport(com.vividsolutions.jts.geom.Point newVal){
spot = newVal;
}
```
``` /**
* Изменяет оригинальный объект sport
*/
public void setSport(com.vividsolutions.jts.geom.Point newVal){
sport = newVal;
}
```
Независимо от того, какой параметр `codewrite.bean.geometry.serial.type` был выбран, тип поля Geometry всегда будет JTS Geometry типом.
### Поддержка Jackson
JTS Geometry объект не является стандартным Java Bean и поэтому не может автоматически сериализоваться и десериализоваться Jackson. Поэтому требуется реализовать пользовательские сериализаторы и десериализаторы для Geometry объекта.
Сериализатор для JTS Geometry класса реализован [gu.sql2java.geometry.jackson.GeometryDeserializer](sql2java-base/src/main/java/gu/sql2java/geometry/jackson/GeometryDeserializer.java)
Десериализатор для JTS Geometry класса реализован [gu.sql2java.geometry.jackson.GeometrySerializer](sql2java-base/src/main/java/gu/sql2java/geometry/jackson/GeometrySerializer.java)
Это позволяет использовать аннотации `@JsonDeserialize` и `@JsonSerialize` для определения пользовательских сериализаторов и десериализаторов для членов класса:
```java
@com.fasterxml.jackson.databind.annotation.JsonDeserialize(using = gu.sql2java.geometry.jackson.GeometryDeserializer.class)
@com.fasterxml.jackson.databind.annotation.JsonSerialize(using = gu.sql2java.geometry.jackson.GeometrySerializer.class)
```
``````java
@JsonSerialize(using = gu.sql2java.geometry.jackson.GeometrySerializer.class)
private com.vividsolutions.jts.geom.Point sport;
```
Пример прямого использования пользовательского сериализатора и десериализатора можно найти в тесте: [GeometryJacksonTest](sql2java-base/src/test/java/gu/sql2java/GeometryJacksonTest.java)### Поддержка Fastjson
Объекты JTS Geometry не являются стандартными Java Beans и поэтому автоматически не могут быть сериализованы и десериализованы с помощью Fastjson. Поэтому требуется реализовать пользовательских сериализаторов и десериализаторов для объектов Geometry.
Базовый класс для пользовательской сериализации и десериализации типов JTS Geometry с использованием Fastjson — это [gu.sql2java.geometry.fastjson.GeometryCodec](sql2java-base/src/main/java/gu/sql2java/geometry/fastjson/GeometryCodec.java).
Ниже представлен подробный список соответствия между классами JTS Geometry и пользовательскими классами сериализации и десериализации:
| Класс JTS Geometry | Классы пользовательской сериализации и десериализации |
| ------------------------------------------------------- | ------------------------------------------------------ |
| `com.vividsolutions.jts.geom.Geometry` | [gu.sql2java.geometry.fastjson.GeometryCodec](sql2java-base/src/main/java/gu/sql2java/geometry/fastjson/GeometryCodec.java) |
| `com.vividsolutions.jts.geom.Point` | [gu.sql2java.geometry.fastjson.PointCodec](sql2java-base/src/main/java/gu/sql2java/geometry/fastjson/PointCodec.java) |
| `com.vividsolutions.jts.geom.LineString` | [gu.sql2java.geometry.fastjson.LineStringCodec](sql2java-base/src/main/java/gu/sql2java/geometry/fastjson/LineStringCodec.java) |
| `com.vividsolutions.jts.geom.Polygon` | [gu.sql2java.geometry.fastjson.PolygonCodec](sql2java-base/src/main/java/gu/sql2java/geometry/fastjson/PolygonCodec.java) |
| `com.vividsolutions.jts.geom.GeometryCollection` | [gu.sql2java.geometry.fastjson.GeometryCollectionCodec](sql2java-base/src/main/java/gu/sql2java/geometry/fastjson/GeometryCollectionCodec.java) |#### Пример использования аннотаций
Ниже представлен пример использования аннотации `@JSONField`, чтобы определить пользовательскую сериализацию и десериализацию полей класса:
```java
@com.alibaba.fastjson.annotation.JSONField(
serializeUsing = gu.sql2java.geometry.fastjson.PointCodec.class,
deserializeUsing = gu.sql2java.geometry.fastjson.PointCodec.class)
private com.vividsolutions.jts.geom.Point spot;
```
Пример прямого цитирования с использованием пользовательских сериализаторов и десериализаторов:
Для примера использования см.: [gu.sql2java.GeometryFastjsonTest](sql2java-base/src/test/java/gu/sql2java/GeometryFastjsonTest.java)
#### GeometryInit
[gu.sql2java.geometry.fastjson.GeometryInit](sql2java-base/src/main/java/gu/sql2java/geometry/fastjson/GeometryInit.java) используется для глобальной настройки сериализатора и десериализатора JTS Geometry для FastJson. Это позволяет установить все пользовательские сериализаторы и десериализаторы JTS Geometry в качестве глобальных для FastJson.
Когда требуется отдельная сериализация и десериализация объектов JTS Geometry, можно использовать метод `GeometryInit.init()` для выполнения глобальной инициализации, чтобы гарантировать правильную работу FastJson с объектами JTS Geometry.
Пример:
```java
@Test
public void test2Fastjson() {
try {
GeometryInit.init();
String wkt = "POINT (1 -1)";
Point point = GeometryDataCodec.DEFAULT_INSTANCE.fromWKT(wkt, Point.class);
log("point {}", JSON.toJSONString(point));
assertTrue(wkt.equals(point.toText()));
} catch (ParseException e) {
e.printStackTrace();
assertTrue(false);
}
}
```
## Фильтрация статических полейНезависимо от того, используются ли Thrift RPC или Spring Web сервисы, входные и выходные параметры методов службы должны передаваться через сеть между сервером и клиентом. Для реализации передачи данных объекты данных отправителя сериализуются (в виде JSON или двоичного потока данных), а получатель затем десерилизует эти данные обратно в исходные объекты данных.
С версии 3.32.0 sql2java добавил возможность фильтрации статических полей, что позволяет указывать видимость полей при генерации классов объектов базы данных.
**Видимость** поля относится к тому, видимым является это поле для получателя данных или нет. Управление этим осуществляется за счет игнорирования невидимых полей при сериализации/десериализации объектов таблицы базы данных.
Реализация заключается в том, что sql2java-generator использует аннотации Jackson, Fastjson и Thrift для указания игнорирования этих полей при сериализации/десериализации объектов таблицы. Примеры см. в разделе **«SCOPE@@EPOSC»**
### Определение видимости полей
В sql2java видимость полей определяется с помощью перечисления `gu.sql2java.ColumnVisibility`.| Перечисляемое значение | Видимость в JSON | Видимость в Thrift | Описание |
|--------------------------|------------------|--------------------|---------------------------------------------------------------------------|
| PUBLIC | true | true | Поле всегда видимо |
| PRIVATE | false | false | Поле всегда скрыто |
| READ_ONLY | true | false | Поле доступно только для чтения |
| WRITE_ONLY | false | true | Поле доступно только для записи |Таким образом, можно контролировать видимость полей в зависимости от требований к сериализации и десериализации объектов таблицы базы данных.
| ----------- | ------------ | -------------- | ------------------------------------------------------------ |
| **DEFAULT** | true | true | По умолчанию все поля видимы |
| **LOCAL** | false | false | Только локально видимо, при взаимодействии с удаленной стороной (Spring WEB, Thrift RPC) невидимо |
| **THRIFT** | false | true | Видимо при передаче данных через Thrift RPC, клиент и сервер Thrift RPC видят данные |
| **JSON** | true | false | Видимо при сериализации в JSON, при взаимодействии клиента и сервера Spring WEB (Spring WEB использует Jackson для сериализации и десериализации), также применимо при использовании FastJson для сериализации и десериализации объектов базы данных |
### Определение видимости
Определяется способ установки видимости полей двумя методами: первый — путём указания метки `SCOPE@@EPOSC` в комментариях к столбцам таблицы в SQL-запросах, см. раздел **«SCOPE@@EPOSC»**, второй — путём конфигурации в файле параметров sql2java (`sql2java.properties`), см. раздел **«Параметры конфигурации»** `(6/8)`.
---
Таким образом, можно контролировать видимость полей в зависимости от требований к сериализации и десериализации объектов таблицы базы данных.
| ----------- | ------------ | -------------- | ------------------------------------------------------------ |
| **DEFAULT** | true | true | По умолчанию все поля видимы |
| **LOCAL** | false | false | Только локально видимо, при взаимодействии с удаленной стороной (Spring WEB, Thrift RPC) невидимо |
| **THRIFT** | false | true | Видимо при передаче данных через Thrift RPC, клиент и сервер Thrift RPC видят данные |
| **JSON** | true | false | Видимо при сериализации в JSON, при взаимодействии клиента и сервера Spring WEB (Spring WEB использует Jackson для сериализации и десериализации), также применимо при использовании FastJson для сериализации и десериализации объектов базы данных |
### Определение видимости
Определяется способ установки видимости полей двумя методами: первый — путём указания метки `SCOPE@@EPOSC` в комментариях к столбцам таблицы в SQL-запросах, см. раздел **«SCOPE@@EPOSC»**, второй — путём конфигурации в файле параметров sql2java (`sql2java.properties`), см. раздел **«Параметры конфигурации»** `(6/8)`.## Аннотация
### @Sql2javaLocalConfig
С версии 3.32.6 добавлена аннотация `@Sql2javaLocalConfig`, которая используется для определения конфигураций времени выполнения Sql2java в сервисных методах или классах. В настоящее время единственным свойством является `resetModifiedIfEqual`. При определении типа Java Bean в этом поле после успешной десериализации JSON в объект Java Bean вызывается метод `BaseBean.resetModifiedIfEqual`, который нормализует объект, гарантируя, что метка modified будет установлена только для полей, значения которых отличаются от значений записей в базе данных.#### RuntimeConfigInterceptor
Для активации аннотации `@Sql2javaLocalConfig` в среде Spring требуется использовать `RuntimeConfigInterceptor`. Этот интерцептор устанавливает объект конфигурации времени выполнения Sql2java (`gu.sql2java.config.RuntimeConfig`) перед тем как HTTP-запрос будет обработан, а затем удаляет его после завершения метода. Конфигурация, созданная аннотацией `@Sql2javaLocalConfig`, хранится в объекте `RuntimeConfig`.
#### Запуск RuntimeConfig интерцептора
Для запуска интерцептора RuntimeConfig достаточно указать пакет, содержащий конфигурацию `RuntimeConfigInterceptor` (`FilterInterceptorConfig`) в аннотации запуска Spring (`@SpringBootApplication`). Это активирует фильтры beanfilter, определённые в сервисных методах.
```java
import org.springframework.boot.autoconfigure.SpringBootApplication;
import gu.sql2java.config.spring.*;
```
```java
/**
* Конфигурация запуска приложения
*/
@SpringBootApplication(scanBasePackageClasses = {RuntimeConfigInterceptor.class})
public class ApplicationBoot {
//////. . . . /////
}
```
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Комментарии ( 0 )