Фон
- Spring 3.x, JPA 2.0, Hibernate 4.x, Postgresql 9.x.
- Работа над сопоставленным классом Hibernate с свойством enum, которое я хочу сопоставить с перечислением Postgresql.
проблема
Запрос с предложением where в столбце перечисления вызывает исключение.
org.hibernate.exception.SQLGrammarException: could not extract ResultSet
...
Caused by: org.postgresql.util.PSQLException: ERROR: operator does not exist: movedirection = bytea
Hint: No operator matches the given name and argument type(s). You might need to add explicit type casts.
Код (сильно упрощен)
SQL:
create type movedirection as enum (
'FORWARD', 'LEFT'
);
CREATE TABLE move
(
id serial NOT NULL PRIMARY KEY,
directiontomove movedirection NOT NULL
);
Hibernate сопоставленный класс:
@Entity
@Table(name = "move")
public class Move {
public enum Direction {
FORWARD, LEFT;
}
@Id
@Column(name = "id")
@GeneratedValue(generator = "sequenceGenerator", strategy=GenerationType.SEQUENCE)
@SequenceGenerator(name = "sequenceGenerator", sequenceName = "move_id_seq")
private long id;
@Column(name = "directiontomove", nullable = false)
@Enumerated(EnumType.STRING)
private Direction directionToMove;
...
// getters and setters
}
Java, которая вызывает запрос:
public List<Move> getMoves(Direction directionToMove) {
return (List<Direction>) sessionFactory.getCurrentSession()
.getNamedQuery("getAllMoves")
.setParameter("directionToMove", directionToMove)
.list();
}
Запрос xibernate xml:
<query name="getAllMoves">
<![CDATA[
select move from Move move
where directiontomove = :directionToMove
]]>
</query>
Поиск проблемы
- Запрос по
id
вместо enum работает, как ожидалось. -
Java без взаимодействия с базами данных работает нормально:
public List<Move> getMoves(Direction directionToMove) { List<Move> moves = new ArrayList<>(); Move move1 = new Move(); move1.setDirection(directionToMove); moves.add(move1); return moves; }
-
createQuery
вместо запроса в XML, аналогично примеруfindByRating
в Apache JPA и Enums через @Enumerated документацию, дает то же исключение. - Запросить в psql с помощью
select * from move where direction = 'LEFT';
работает, как ожидалось. - Hardcoding,
where direction = 'FORWARD'
в запросе в XML работает. -
.setParameter("direction", direction.name())
не совпадает с параметрами.setString()
и.setText()
, исключение изменяется на:Caused by: org.postgresql.util.PSQLException: ERROR: operator does not exist: movedirection = character varying
Попытки разрешения
-
Пользовательский
UserType
как предлагается в этом принятом ответе qaru.site/info/316702/... а также:@Column(name = "direction", nullable = false) @Enumerated(EnumType.STRING) // tried with and without this line @Type(type = "full.path.to.HibernateMoveDirectionUserType") private Direction directionToMove;
-
Сопоставление с Hibernate
EnumType
как было предложено более высоким, но не принятым ответом qaru.site/info/316702/... по тому же вопросу, что и выше, а также:@Type(type = "org.hibernate.type.EnumType", parameters = { @Parameter(name = "enumClass", value = "full.path.to.Move$Direction"), @Parameter(name = "type", value = "12"), @Parameter(name = "useNamed", value = "true") })
С двумя и без двух параметров после просмотра qaru.site/info/355864/...
- Пробовал аннотировать геттер и сеттер, как в этом ответе qaru.site/info/355866/....
- Не пробовал
EnumType.ORDINAL
потому что я хочу придерживатьсяEnumType.STRING
, который менее хрупкий и более гибкий.
Другие примечания
Конвертер типа JPA 2.1 не должен быть необходимым, но это не вариант, поскольку я сейчас на JPA 2.0.