hibernate PersistentAttributeInterceptor делает объединение не работоспособным - PullRequest
0 голосов
/ 09 октября 2019

Я использую springboot (2.1.9.RELEASE) и hibernate (5.4.6.Final) для разработки программы, и мне нужно lazyload поля типа String (changelog), поэтому я использую PersistentAttribute Interceptable, поля типа строкиможет быть ленивая загрузка, но таблица соединения ManyToMany не работает. Вот код

@Entity
@Table(name = "categories")
public class Category implements Serializable {

  private static final long serialVersionUID = 911243379555328411L;

  @Id
  @Column(name = "id")
  private Long id;

  private String name;

  private int position;

  @ManyToOne
  @JoinColumn(name = "parent_id")
  private Category parent;

  @OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
  @OrderColumn(name = "position")
  List<Category> children;

  @ManyToMany(mappedBy = "categories")
  private Set<Item> items;

  // getter AND setter
}

@Entity
@Table(name = "items")
public class Item implements Serializable, PersistentAttributeInterceptable {

    private static final long serialVersionUID = 6129011836002505114L;

    @Id
    @Column(name = "id")
    private Long id;

    @Column(name = "table_name")
    private String table;

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

    @Lob
    @Basic(fetch = FetchType.LAZY)
    private String changelog;


    @ManyToMany
    @JoinTable(name = "category_items", joinColumns = @JoinColumn(name = "item_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "category_id", referencedColumnName = "id"))
    private Set<Category> categories;


    @Transient
    private PersistentAttributeInterceptor interceptor;

    // id, table, description getter setter

    public String getChangelog() {
        if (interceptor != null) {
            return (String) interceptor.readObject(this, "changelog", changelog);
        }
        return null;
    }

    public void setChangelog(String changelog) {
        if (changelog == null) {
            if (interceptor != null) {
                interceptor.writeObject(this, "changelog", this.changelog, changelog);
                return;
            }
        }
        this.changelog = changelog;
    }


    public Set<Category> getCategories() {
        if (null == categories) {
            categories = new HashSet<>();
        }
        if (interceptor != null) {
            return (Set<Category>) interceptor.readObject(this, "categories", categories);
        }
        return categories;
    }

    public void setCategories(Set<Category> categories) {
        if (categories == null) {
            if (interceptor != null) {
                interceptor.writeObject(this, "categories", this.categories, categories);
                return;
            }
        }
        this.categories = categories;
    }

    @Override
    public PersistentAttributeInterceptor $$_hibernate_getInterceptor() {
        return interceptor;
    }

    @Override
    public void $$_hibernate_setInterceptor(PersistentAttributeInterceptor persistentAttributeInterceptor) {
        interceptor = persistentAttributeInterceptor;
    }
}

Код тестового примера

@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class ItemRepositoryTest {
  @Autowired ItemRepository itemRepository;
  @Autowired CategoryRepository categoryRepository;

  @Transactional
  @Rollback(false)
  @Test
  public void save() {
    Category root = buildCategory(1L, "root", 0);

    Category child1 = buildCategory(2L, "child1", 1);
    Category child2 = buildCategory(3L, "child2", 2);
    Category child3 = buildCategory(4L, "child3", 3);

    List<Category> children = Arrays.asList(child1, child2, child3);
    root.setChildren(children);

    List<Category> categories1 = Arrays.asList(root, child1, child2, child3);

    categoryRepository.saveAll(categories1);
    categoryRepository.flush();

    Item item = buildItem(1L, "SecuMain", "test");

    Set<Category> categories = new HashSet<>();
    categories.add(child1);
    item.setCategories(categories);

    itemRepository.saveAndFlush(item);
    assertTrue(true);
  }
}

После выполнения тестового примера данные были вставлены в категориии таблица элементов, но у joinTable category_items нет данных. Если Item не использует PersistentAttributeAttributeable, данные могут быть записаны в таблицу элементов категории, но журнал изменений не может быть загружен с отложенной загрузкой.

1 Ответ

0 голосов
/ 22 октября 2019

У меня похожая проблема с @OneToMany вместо @ManyToMany (с Hibernate 5.4.2). Я думаю, это ошибка в спящем режиме. Если вы используете PersistentAttributeInterceptable, вы больше не сможете использовать Lazy Loading в этом классе без перехватчика. Попробуйте @ManyToMany (fetch = FetchType.EAGER), чем это должно работать. Но это, возможно, не то, что вам нужно, потому что у вас все еще есть проблема производительности с EAGER Loading.

...