#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. Я решил свою проблему, используя обходной путь:
- Удалено объявление типа перечисления из схемы SQL
- Заменено поле перечисления в схеме SQL типом Varchar (но не в классе модели Java)
- Модифицированный слой 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"));
}
}