Как заполнить коллекцию на основе существующих столбцов с помощью Hibernate - PullRequest
0 голосов
/ 18 июня 2020

У меня есть две существующие таблицы, у которых есть свойство (someField в примере кода).

Что я хочу сделать: Заполнить коллекцию Foo.bars всеми Bar объектами, которые имеют одинаковые someField значение как Foo сущность, которую я загружаю.

Я не хочу создавать дополнительную таблицу соединений, так как не хочу явно обновлять отношение.

Как это реализовать с помощью аннотаций к объектам и / или их полям?

Некоторые пояснения:

  1. Два столбца someField изменяются независимо.
  2. Для любого из двух столбцов нет ограничения уникального ключа (поэтому я добавил @ManyToMany).
  3. Мне не нужны отношения внешнего ключа или каскадирование.
  4. Столбцы не должны обновляться, если коллекция изменена. Я хочу, чтобы спящий режим заполнял коллекцию только при загрузке объекта Foo.
  5. Я пробовал использовать @JoinFormula без какого-либо отношения @XtoY и не смог заставить его работать.
  6. отношение моделируется только с одной стороны, так как я никогда не забочусь о Foo s, если у меня есть экземпляр Bar.

Я использую spring-boot-starter-data- jpa 2.3, который использует Hibernate 5.4.15

@Entity
public class Foo{

  @Id
  @GeneratedValue
  private int id;

  private int someField;

  @ManyToMany
  private Set<Bar> bars;

}

@Entity
public class Bar{

  @Id
  @GeneratedValue
  private int id;

  private int someField;

}

Обновление 22.06.2020

Поскольку я не смог express использовать свой вариант использования, я создал минимальный проект github .

Единственными двумя способами, которые я нашел для реализации требуемого поведения, были:

  1. Реализация явного логирования контроллера c, который загружает связанные экземпляры Bar вручную.

  2. Реализовать аспект AspectJ, который присоединяется к FooRepository методам загрузки, которые вручную выбирают связанные Bar экземпляры.

Оба "ошиблись" так как я думал, что это попадает в сферу гибернации и создает много дополнительных d b запросы.

1 Ответ

1 голос
/ 18 июня 2020

Итак, во-первых, я не понимаю, почему вы использовали @ManyToMany, потому что это для отношений n-to-n, а ваше на это не похоже.

Вы можете смоделировать parent- дочерние отношения двумя способами, наиболее эффективным является сопоставление ManyToOne, при котором дочерний элемент управляет внешним ключом для родительского элемента:

@Entity
public class Parent {

  @Id
  @GeneratedValue
  private int id;

  private int someField;

}

@Entity
public class Child {

  @Id
  @GeneratedValue
  private int id;

  private int someField;

  @ManyToOne(fetch = FetchType.LAZY)
  @JoinColumn(
    name = "someField",
    referencedColumnName = "someField",
    unique = false,
    updateable = false,
    insertable = false)
  private Parent parent;

}

Вы можете использовать запросы JPQL / Criteria для получения всего, что вам нужно.

Подробнее об ассоциациях ManyToOne . А здесь еще немного .

См. @ JoinColumn docs для атрибутов вроде 'unique', et c.

И если вы настаивайте на том, чтобы сделать наоборот, это тоже сработает:

@Entity
public class Parent {

  @Id
  @GeneratedValue
  private int id;

  private int someField;

  @OneToMany(
    // cascade = What operations do you want to cascade? Who is the owner of the relationship?
    // orphanRemoval = Do you want to delete orphaned children?
  )
  @JoinColumn(name = "someField",
    unique = false,
    updateable = false,
    insertable = false)
  private List<Child> children = new ArrayList<>();

}

@Entity
public class Child {

  @Id
  @GeneratedValue
  private int id;

  private int someField;

}

Это однонаправленное отображение, но вы можете добавить «родительскую» ассоциацию к дочернему, если хотите. Затем вам нужно добавить методы, чтобы убедиться, что они синхронизированы ([см. Здесь]) 4

Если они не уникальны и внешнего ключа нет, я не уверен, что это будет работай. Но в этом случае вы можете использовать @JoinFormula, чтобы предоставить запрос SQL для присоединения.

...