Hibernate делает разную структуру таблиц
Есть класс entity:
@Entity
@Table(name="data_mapper")
public class DataMapper {
@Getter
@Setter
@Id
@Column(name="id")
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "DataMapperGenerator")
@SequenceGenerator(name = "DataMapperGenerator", sequenceName = "DATA_MAPPER_ID")
private Integer id;
@Getter
@Setter
@Column(name="name", unique = true)
private String name;
@Getter
@Setter
@Column(name="description")
private String description;
@Getter
@Embedded
@ElementCollection(fetch = FetchType.EAGER)
@CollectionTable(name = "data_mapper__definition")
private Map<String, DataDefinition> dataDefinitions=new HashMap();
...
}
и класс embeddable:
@Embeddable
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class DataDefinition{
public static enum DataType{
STRING,
BOOLEAN,
DOUBLE,
LONG,
VOID
}
@Column(name="field")
private String field;
@Column(name="type")
@Enumerated(EnumType.STRING)
private DataType type;
}
который выступает в качестве значения Map в entity.
БД Postgresql Создаю чистую базу на одной машине (Win7) Запускаю собранный проект, получаю:
CREATE TABLE public.data_mapper__definition
(
data_mapper_id integer NOT NULL,
field character varying(255) COLLATE pg_catalog."default",
type character varying(255) COLLATE pg_catalog."default",
hash integer NOT NULL,
value character varying(255) COLLATE pg_catalog."default" NOT NULL,
CONSTRAINT data_mapper_definitions_pkey PRIMARY KEY (data_mapper_id, hash, value),
CONSTRAINT fkaafs5xfb22lsemqus8s0fprd6 FOREIGN KEY (data_mapper_id)
REFERENCES public.data_mapper (id) MATCH SIMPLE
ON UPDATE NO ACTION
ON DELETE NO ACTION,
CONSTRAINT fknryw7bseacxjmo5wtsdcuvyey FOREIGN KEY (data_mapper_id)
REFERENCES public.data_mapper (id) MATCH SIMPLE
ON UPDATE NO ACTION
ON DELETE NO ACTION
)
Запускаю этот же проект на другой машине (Win10), получаю такую структуру:
CREATE TABLE public.data_mapper__definition
(
data_mapper_id integer NOT NULL,
field character varying(255) COLLATE pg_catalog."default",
type character varying(255) COLLATE pg_catalog."default",
coder smallint NOT NULL,
hash integer NOT NULL,
value bytea NOT NULL,
CONSTRAINT data_mapper__definition_pkey PRIMARY KEY (data_mapper_id, coder, hash, value),
CONSTRAINT fkaafs5xfb22lsemqus8s0fprd6 FOREIGN KEY (data_mapper_id)
REFERENCES public.data_mapper (id) MATCH SIMPLE
ON UPDATE NO ACTION
ON DELETE NO ACTION
)
То есть, во втором случае ключ String от Map из character varying(255) превращается в binary data и ещё добавляется столбец coder.
Работает всё и там и там, данные вставляются и достаются, только совсем в разном виде. А мне надо перенести базу из одной машины на другую.
pom:
...
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.2.10.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>5.2.10.Final</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.2.2</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.7.RELEASE</version>
<type>jar</type>
</dependency>
...
Версия Postgresql и там и там одинаковая (10.6.1) Не могу понять, почему hibernate так делает и как его заставить хранить значение ключа Map гарантированно в виде varchar Помогите, пожалуйста
Ответы (1 шт):
Решил проблему. Ещё раз перечитал доки по hibernate и всё наладилось:) Убрал @Embedded и добавил @MapKeyColumn. До этого, похоже, hibernate пытался найти для String @Embeddable класс и творил непонятно что, т.к. не знал, как себя вести с тем набором аннотаций и типом ключа Map, которые я ему написал, хотя, кто знает, что он пытался и от чего у него зависел механизм построения структуры таблицы, но косяк был в неправильных аннотациях. Теперь вот так
@ElementCollection(fetch = FetchType.EAGER)
@MapKeyColumn(name="value")
@CollectionTable(name = "data_mapper__definition")
private Map<String, DataDefinition> dataDefinitions=new HashMap();
Hibernate создаёт таблицу с колонками data_mapper_id, field, type, value. Удалил колонку hash в заполненной бд, поправил primary key, перенёс на новую машину и всё заработало.