LINUX.ORG.RU

Как связать два класса с полями типа Map<String, String> отношением @OneToMany ?

 , , ,


0

1

Приветствую всех.

Знатоки hibernate и JPA помогите связать две сущности, у которых есть поля типа Map<String, String>, отношением @OneToMany.

Сам код вот:

@Entity
class Entity1 {
    @Id
    @Column(name="entity1_id")
    private Long id;

    @Column(name="entity1_name")
    private String name;

    @ElementCollection
    @CollectionTable(
        name = "map1",
        joinColumns = @JoinColumn(name = "entity1_id"))
    @MapKeyColumn(name = "map1_key")
    @Column(name = "map1_value")
    private Map<String, String> map1 = new HashMap<>();

    ...
}

@Entity
class Entity2 {
    @Id
    @Column(name="entity2_id")
    private Long id;

    @Column(name="entity2_name")
    private String name;

    @ElementCollection
    @CollectionTable(name = "map2",
        joinColumns = @JoinColumn(name = "entity2_id"))
    @MapKeyColumn(name = "map2_key")
    @Column(name = "map2_value")
    private Map<String, String> map2 = new HashMap<>();

    // не работает
    @OneToMany(cascade = CascadeType.ALL)
    @JoinTable(
            name = "map2",
            joinColumns = @JoinColumn(name = "entity2_id"),
            inverseJoinColumns = @JoinColumn(name = "entity1_id"))
    private Set<Entity1> entity1s;
    ...
}

База данных создается скриптом:

create table entity1
(
  entity1_id   int         not null unique,
  entity1_name varchar(10) not null,
  primary key (entity1_id)
);

create table map1
(
  entity1_id  int     not null,
  map1_key    int     not null,
  map1_value  decimal not null,
  primary key (entity1_id, map1_key),
  foreign key (entity1_id) references entity1 (entity1_id)
    on delete cascade
    on update cascade
);

create table entity2
(
  entity2_id   int         not null unique,
  entity2_name varchar(20) not null,
  primary key (entity2_id)
);

create table map2
(
  entity2_id int     not null,
  map2_key   int     not null,
  map2_value decimal not null,
  entity1_id    int     not null,
  primary key (entity2_id, entity2_key),
  foreign key (entity2_id) references entity2 (entity2_id)
    on delete cascade
    on update cascade,
  foreign key (entity1_id) references entity1 (entity1_id)
    on delete cascade
    on update cascade
);

insert into entity1 (entity1_id, entity1_name)
values (1, 'entity11'),
       (2, 'entity12'),
       (3, 'entity13');

insert into map1 (entity1_id, map1_key, map1_value)
values (1, 0, 0.1),
       (1, 1, 0.1),
       (1, 2, 0.1),
       (2, 3, 0.2),
       (2, 4, 0.2),
       (2, 5, 0.2),
       (3, 6, 0.3),
       (3, 7, 0.3),
       (3, 8, 0.3);

insert into entity2 (entity2_id, entity2_name)
values (1, 'entity21'),
       (2, 'entity22'),
       (3, 'entity23');

insert into map2 (entity2_id, map2_key, map2_value, entity1_id)
values (1, 0, 10, 1),
       (1, 1, 20, 1),
       (1, 2, 10, 2),
       (1, 3, 10, 2),
       (2, 0, 20, 2),
       (2, 1, 20, 2),
       (2, 2, 20, 3),
       (2, 3, 20, 3),
       (3, 0, 10, 3),
       (3, 1, 10, 3),
       (3, 2, 10, 1),
       (3, 3, 10, 1);

На уровне базы данных всё работает. То есть, заполняем таблицы entity1 & 2, вводим (key, value) для entity1. Затем вводим ключи и значения для entity2, и одновременно устанавливаем связи.

Как это реализовать с помощью hibernate?


Не понял вопроса.
Что мешает добавить в Entity1 поле @One2Many а в Entity2 @Many2One?

Upd

@JoinTable(
            name = "map2",
            joinColumns = @JoinColumn(name = "entity2_id"),
            inverseJoinColumns = @JoinColumn(name = "entity1_id"))


По идее всего этого не надо.
Надо указывать mappedBy = «<field>» в @One2Many

WatchCat ★★★★★ ()
Последнее исправление: WatchCat (всего исправлений: 2)
Ответ на: комментарий от WatchCat

Прописал в Entity1:

    @OneToMany(cascade = CascadeType.ALL)
    @JoinTable(
            name = "map2",
            joinColumns = @JoinColumn(name = "entity1_id"),
            inverseJoinColumns = @JoinColumn(name = "entity2_id"))
    private Set<Entity2> entity2s = new HashSet<>();

Прописал в Entity2:

    @OneToMany(cascade = CascadeType.ALL)
    @JoinTable(
            name = "map2",
            joinColumns = @JoinColumn(name = "entity2_id"),
            inverseJoinColumns = @JoinColumn(name = "entity1_id"))
    private Set<Entity1> entity1s = new HashSet<>();

Падает с ошибкой

ERROR: ERROR: null value in column "map2_key" violates not-null constraint
  Detail: Failing row contains (4, null, null, 4).

Причем откуда появляются null в map2_key & map2_value я понять не могу.

Сам код вот здесь можно посмотреть

pol01 ()
Ответ на: комментарий от pol01

Ты не понял.
Должно выглядеть примерно так:

class Entity1 {
...
    @ManyToOne
    private Entity2 parent
...
}

class Entity2 {
    @OneToMany(mappedBy = "parent" )
    private Set<Entity1> entity1s;
}

А все эти JoinTable в простом случае не нужны.

WatchCat ★★★★★ ()
Последнее исправление: WatchCat (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.