java - hibernate PersistentAttributeInterceptor使jointable不起作用

标签 java hibernate jpa

我使用springboot(2.1.9.RELEASE)和hibernate(5.4.6.Final)来开发程序,并且我需要延迟加载一个String类型字段(changelog),所以我使用PersistentAttribute Interceptable,字符串类型字段可以延迟加载,但是ManyToMany的join Table不行。代码如下

@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);
  }
}

运行测试用例后,数据已插入到categories和items表中,但joinTablecategory_items没有数据。 如果Item不使用PersistentAttributeAttributeable,数据可以写入category-items表,但changelog不能延迟加载。

最佳答案

我有一个类似的问题,使用 @OneToMany 而不是 @ManyToMany (使用 Hibernate 5.4.2)。我猜这是一个 Hibernate Bug。如果您使用 PersistentAttributeInterceptable,那么您将无法在没有拦截器的情况下在此类中使用延迟加载。尝试 @ManyToMany(fetch = FetchType.EAGER) ,它应该可以工作。但这可能不是您想要的,因为您仍然遇到急切加载的性能问题。

关于java - hibernate PersistentAttributeInterceptor使jointable不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58296228/

相关文章:

java - J2EE war 文件重新部署更改未反射(reflect)出来

java - 查找两个不同列表是否包含完全相同元素的简单方法?

java - java中删除动态数组

java - Tomcat - Eclipse 中的服务器

Hibernate:多对多连接表的标准?

hibernate - 在 JBoss/WildFly 中注入(inject) EntityManager

java - JPA PessimisticLockScope.NORMAL 和锁定 "relationships"

java - Springframework.dao.InvalidDataAccessResourceUsageException hibernate .SQLGrammarException MySQLSyntaxErrorException

java - JPA 清除缓存以读取一项

java - 如何在 JPA/Hibernate 中与现有数据库建立表关联?