Почему аннотация JDBI 3 @ColumnName не работает? - PullRequest
0 голосов
/ 02 ноября 2018

Я хочу использовать аннотации jdbi 3 @ColumnName для сопоставления имени столбца таблицы и поля Java-компонента, но во время выполнения jdbi выдает исключение. Мой вопрос: почему выбрасывается исключение? Мое использование неверно? Как решить эту проблему? Спасибо

Таблица базы данных:

CREATE TABLE `department` (
  `id` bigint(20)  NOT NULL AUTO_INCREMENT,
  `name` varchar(32) NOT NULL DEFAULT '' ,
  `business_system` tinyint(4)  NOT NULL ,
  `functional` tinyint(4)  NOT NULL ,
  `remark` varchar(100) NOT NULL DEFAULT ''
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Java Bean:

@Data
public class Department {
    private Long id;

    @NotNull
    @Size(min = 3, max = 20)
    private String name;

    @NotNull
    @ColumnName("business_system")
    private Integer businessSystem;

    @NotNull
    @ColumnName("functional")
    private Integer functional;

    @Max(value = 200)
    private String remark;
  }

Обновление JDBI:

@Override
public Long create(Department department) {
    String sql = "INSERT INTO department (name, business_system, functional, remark)"
        + "VALUES (:name, :business_system, :functional, :remark)";

return jdbi.withHandle(handle -> handle.createUpdate(sql)
    .bindBean(department)
    .executeAndReturnGeneratedKeys()
    .mapTo(Long.class)
    .findOnly());

}

Результат выполнения модульного теста:

org.jdbi.v3.core.statement.UnableToExecuteStatementException: Unable to 
execute, no named parameter matches 'business_system'. [statement:"INSERT INTO 
department (name, business_system, functional, remark)VALUES (:name, 
:business_system, :functional, :remark)", rewritten:"INSERT INTO department 
(name, business_system, functional, remark)VALUES (:name, :business_system, 
:functional, :remark)", parsed:"ParsedSql{sql='INSERT INTO department (name, 
business_system, functional, remark)VALUES (?, ?, ?, ?)', 
parameters=ParsedParameters{positional=false, parameterNames=[name, 
business_system, functional, remark]}}", 
arguments:{ positional:{}, named:{}, finder:[{lazy bean property arguments 
"Department(id=null, name=test, businessSystem=2, functional=2, 
remark=test)"]}]

1 Ответ

0 голосов
/ 13 декабря 2018

JDBI сопровождающий здесь. Четыре недоразумения сговорились, чтобы ваш код не работал:

Во-первых, @ColumnName определяет одностороннее сопоставление, используемое только для сопоставления имен столбцов со свойствами объекта / полями / параметрами конструктора. Поэтому BeanMapper будет учитывать аннотацию @ColumnName, а bindBean() игнорирует ее.

Во-вторых, BeanMapper обнаруживает @ColumnName только в методах получения и установки, но не в полях. Поскольку вы используете аннотацию @Data от Lombok, аннотация @ColumnName фактически выводится на поле. У Lombok есть супер уродливый способ указать аннотации для получателя или установщика:

@NotNull
@Getter(onMethod=@__(@ColumnName("business_system")))
private Integer businessSystem;

@NotNull
@Getter(onMethod=@__(@ColumnName("functional")))
private Integer functional;

В-третьих, bindBean() связывает именованные параметры на основе имен свойств бина, а не имен столбцов. Таким образом, ваши именованные параметры должны быть в :camelCase вместо :snake_case:

INSERT INTO department (name, business_system, functional, remark)
VALUES (:name, :businessSystem, :functional, :remark)
--                      ^ camel case property name

Наконец, Jdbi 3 уже сопоставляет имена столбцов в виде змеи с именами свойств в случае верблюда из коробки. Например: столбец foo_bar будет автоматически сопоставлен со свойством fooBar, аннотация @ColumnName не требуется.

...