2

I'm annotating my domain model for a shop (with JPA 2, using a Hibernate Provider).

In the shop every product can have a Category. Each category can be assigned to several super- and subcategories, meaning a category "candles" can have "restaurant" and "decoration" as parents and "plain candles" and "multi-wick candles" as children, etc.

Now I want to avoid cyclic references, i. e. a category "a" that has "b" as its parent which in turn has "a" as its parent.

Is there a way to check for cyclic references with a constraint in JPA? Or do I have to write some checks myself, maybe in a @PostPersist-annotated method?

Here's my Category class:

@Entity
public class Category {
    @Id
    @GeneratedValue
    private Long id;

    private String name;

    @ManyToMany
    private Set<Category> superCategories;
    @ManyToMany(mappedBy="superCategories")
    private Set<Category> subCategories;

    public Category() {
    }

    // And so on ..
}
Bob
  • 85
  • 1
  • 4

2 Answers2

1

I believe you would have to check this through a business rule in your code. Why don't you separate these ManyToMany mappings in a separate Entity ? Like for example:

@Entity
@Table(name = "TB_PRODUCT_CATEGORY_ROLLUP")
public class ProductCategoryRollup  {

    private ProductCategory parent;
    private ProductCategory child;

    @Id    
    @GeneratedValue
    public Integer getId() {
        return super.getId();
    }
    @Override
    public void setId(Integer id) {
        super.setId(id);
    }

    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name="ID_PRODUCT_CATEGORY_PARENT", nullable=false)  
    public ProductCategory getParent() {
        return parent;
    }
    public void setParent(ProductCategory parent) {
        this.parent = parent;
    }

    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name="ID_PRODUCT_CATEGORY_CHILD", nullable=false)   
    public ProductCategory getChild() {
        return child;
    }
    public void setChild(ProductCategory child) {
        this.child = child;
    }   

}

In this way, you could before Saving a new entity, query for any existing Parent-Child combination.

Quinn Wilson
  • 7,995
  • 1
  • 22
  • 31
guilhebl
  • 8,330
  • 10
  • 47
  • 66
0

I know I come back to the problem after several years but, I faced this problem, followed all of your resolutions and it didn't work for me. But I found the best solution using @JsonIgnoreProperties which solved the problem perfectly. In fact, I injected @JsonIgnoreProperties into the entity classes linked by a mapping like here:https://hellokoding.com/handling-circular-reference-of-jpa-hibernate-bidirectional-entity-relationships-with-jackson-jsonignoreproperties/

  • 2
    Please don't add the same answer to multiple questions. Answer the best one and flag the rest as duplicates. See [Is it acceptable to add a duplicate answer to several questions?](//meta.stackexchange.com/q/104227) https://stackoverflow.com/questions/54041082/how-to-implement-a-circular-dependency-in-jpa-with-a-class-in-the-middle-of-it/70402562#70402562 – Yunnosch Dec 18 '21 at 10:40
  • https://stackoverflow.com/help/promotion – Yunnosch Dec 18 '21 at 10:42