Как исправить ошибку преобразования данных: JdbcTemplate.update, запись перечисления в базу данных H2

#java #spring #enums #h2 #jdbctemplate

Вопрос:

Я использую PostgreSQL для своего основного кода и H2 для тестирования и получаю разные результаты (тест не проходит). Мой класс с полем типа перечисления

 public class Student {
    private int id;
    private String firstName;
    private String lastName;
    private Gender gender;
}
public enum Gender {
    MALE, FEMALE;
}
 

Схема SQL является

 CREATE TABLE students (
id integer NOT NULL generated BY DEFAULT AS identity,
first_name VARCHAR(255),
last_name VARCHAR(255),
gender GENDER
);
CREATE TYPE gender AS ENUM ('MALE','FEMALE');
 

Мой класс ДАО

 public class JdbcStudentDao {
    private static final String CREATE = "INSERT INTO students (first_name, last_name, gender) VALUES (?, ?, ?)";

    KeyHolder keyHolder = new GeneratedKeyHolder();
    public void create(Student student) {
    jdbcTemplate.update(connection -> {
        PreparedStatement ps = connection
            .prepareStatement(CREATE, Statement.RETURN_GENERATED_KEYS);
        ps.setString(1, student.getFirstName());
        ps.setString(2, student.getLastName());
        ps.setObject(3, student.getGender(), java.sql.Types.OTHER);
        return ps;
    }, keyHolder);
    student.setId((int) keyHolder.getKeys().get("id"));
    }
}
 

В моем методе тестирования:

 Student student = new Student("Name", "Lastname", Gender.MALE);
jdbcStudentDao.create(student);
 

Все работает с PostgreSQL, но тест с H2 завершается ошибкой преобразования данных:

 org.springframework.dao.DataIntegrityViolationException: PreparedStatementCallback; (STUDENTS: ""GENDER"" ""GENDER"")"
Data conversion error converting (STUDENTS: ""GENDER"" ""GENDER"")"; SQL statement:
INSERT INTO students (first_name, last_name, gender) VALUES (?, ?, ?) 
 

Я думаю «java.sql.Типы.ДРУГОЕ», которое я использовал в PreparedStatement для пола, автоматически преобразуется Postgres, но не двигателем H2.
http://www.h2database.com/html/datatypes.html#enum_type говорит, что перечисление отображается в целое число. В этом ли проблема? Есть ли обходной путь?

Ответ №1:

Компонент H2 database engine не поддерживает значения перечисления, как это реализовано в Postgre. Я решил свою проблему, используя обходной путь:

  1. Удалено объявление типа перечисления из схемы SQL
  2. Заменено поле перечисления в схеме SQL типом Varchar (но не в классе модели Java)
  3. Модифицированный слой Dao с использованием .toString() в методах обновления и создания

Теперь тесты корректно выполняются в обеих базах данных.

 public class JdbcStudentDao {
    private static final String CREATE = "INSERT INTO students (first_name, last_name, gender) VALUES (?, ?, ?)";

    KeyHolder keyHolder = new GeneratedKeyHolder();
    public void create(Student student) {
    jdbcTemplate.update(connection -> {
        PreparedStatement ps = connection
            .prepareStatement(CREATE, Statement.RETURN_GENERATED_KEYS);
        ps.setString(1, student.getFirstName());
        ps.setString(2, student.getLastName());
        ps.setString(3, student.getGender().toString());
        return ps;
    }, keyHolder);
    student.setId((int) keyHolder.getKeys().get("id"));
    }
}