У меня проблема с ассоциацией @ManyToMany, если необходимо сохранить «сложную» структуру объектов.
У меня есть Java приложение, использующее Spring Boot (spring-boot) -starter-parent 2.2.5.RELEASE) с JPA (пружинный загрузчик-стартер-данные-jpa). В качестве базы данных я пробовал MySQL и H2. Эффект тот же.
Аннотация 1
Я использую объект List при создании категории и использую тот же объект List при создании объекта item.
Category cat1 = new Category("Cat 1", personList, null);
categoryService.create(cat1);
Item item1 = new Item("Item 1", personList, cat1);
itemService.create(item1);
- В записи категории есть три записи о лицах, назначенные в качестве менеджеров в таблице category_managers
- В записи элемента есть три записи о лицах, назначенные как лица в таблице item_persons
Аннотация 2
Я использую объект List при создании категории и повторно использую список category.getManager при создании объекта item.
Category cat2 = new Category("Cat 2", personList, null);
categoryService.create(cat2);
Item item2 = new Item("Item 2", cat2.getManagers(), cat2);
itemService.create(item2);
- Элемент имеет три записи о людях, назначенных в качестве персон в таблице item_persons
- !!! В категории нет назначений менеджеров в таблице category_managers
Аннотация 3
Теперь та же процедура, что и в резюме 2 с дополнительным назначением и обновлением:
Category cat3 = new Category("Cat 3", personList, null);
categoryService.create(cat3);
cat3.setManagers(personList);
categoryService.update(cat3);
Item item3 = new Item("Item 3", cat3.getManagers(), cat3);
itemService.create(item3);
- В категории есть записи из трех человек, назначенные в качестве менеджеров (см. Таблицу category_managers)
- Для элемента есть записи из трех человек, назначенные в качестве лиц (см. Таблицу item_persons)
Вопросы
Почему задания в Резюме 2 не сохранились?
Разве я не учел что-то?
Не понимаю ли я что-то, что происходит за сцена?
Это может быть особый случай использования, но есть ли какие-то темы или главы, которые мне нужно прочитать снова?
Привет из Штутгарта
Подробное описание
Структура модели
Перс. java:
@Entity
public class Person {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String firstName;
private String lastName;
// Constructors -------------------------------------------------------------------------------
public Person() {}
public Person(String firstName, String lastName) {
super();
this.firstName = firstName;
this.lastName = lastName;
}
// Getters / Setters --------------------------------------------------------------------------
// ...
}
Категория. java:
@Entity
public class Category {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@ManyToMany
private List<Person> managers;
@OneToMany(fetch = FetchType.LAZY)
@JoinColumn(name="category_id", updatable = false)
private List<Item> items;
// Constructors -------------------------------------------------------------------------------
public Category() {}
public Category(String name, List<Person> managers, List<Item> items) {
super();
this.name = name;
this.managers = managers;
this.items = items;
}
// Getters / Setters --------------------------------------------------------------------------
// ...
}
Item. java:
@Entity
public class Item {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@ManyToMany
private List<Person> persons;
@ManyToOne
private Category category;
// Constructors -------------------------------------------------------------------------------
public Item() {}
public Item(String name, List<Person> persons, Category category) {
super();
this.name = name;
this.persons = persons;
this.category = category;
}
// Getters / Setters --------------------------------------------------------------------------
// ...
}
Имущество должно быть продолжено ain лица, назначенные для определенного элемента. Категория свойства должна содержать необязательную категорию, назначенную для нескольких элементов. Менеджерам категории будет назначено свойство person ее элементов.
Очень просто и понятно.
Соответствующие интерфейсы репозитория и классы обслуживания
Интерфейсы репозитория расширяют интерфейс JpaRepository. Классы обслуживания содержат методы для создания, получения, обновления и удаления записей в базе данных. ((Я просто публикую один из них))
@Service
public class PersonService {
@Autowired
PersonRepository personRepo;
public Person create(Person person) {
return personRepo.save(person);
}
public Person get(long id) {
return personRepo.getOne(id);
}
public void update(Person person) {
personRepo.save(person);
}
public void delete(long id) {
personRepo.deleteById(id);
}
}
Три теста
А вот код, демонстрирующий проблему, с которой я сталкиваюсь, при создании записей в базе данных. Есть 3 случая.
@Component
public class DatabaseInitializer implements CommandLineRunner {
@Autowired
CategoryService categoryService;
@Autowired
ItemService itemService;
@Autowired
PersonService personService;
@Override
public void run(String... args) throws Exception {
// Create persons
Person max = personService.create(new Person("Max", "Mad"));
Person sally = personService.create(new Person("Sally", "Silly"));
Person bob = personService.create(new Person("Bob", "Bad"));
List<Person> personList = Arrays.asList(max, sally, bob);
// Case 1 (this works)
// Here we will use the personList object for both the category and the item.
Category cat1 = new Category("Cat 1", personList, null);
categoryService.create(cat1);
Item item1 = new Item("Item 1", personList, cat1);
itemService.create(item1);
// => The category record has three person records assigned as managers (see. category_managers table)
// => The item record has three person records assigned as persons (see. item_persons table)
// Case 2 (this doesn't work)
// Here we will use the personList object to create the category and reuse the category.getManager list to create the item.
Category cat2 = new Category("Cat 2", personList, null);
categoryService.create(cat2);
Item item2 = new Item("Item 2", cat2.getManagers(), cat2);
itemService.create(item2);
// => The category has no managers assignments (see. category_managers table) WHY??
// => The item has three person records assigned as persons (see. item_persons table)
// Case 3 (workaround of case 2)
// Here we will do the same as in case 2, but will do an extra assignment of the managers of the category
Category cat3 = new Category("Cat 3", personList, null);
categoryService.create(cat3);
cat3.setManagers(personList);
categoryService.update(cat3);
Item item3 = new Item("Item 3", cat3.getManagers(), cat3);
itemService.create(item3);
// => The category has three person records assigned as managers (see. category_managers table)
// => The item has three person records assigned as persons (see. item_persons table)
}
}