Hibernate JPA双向一对多结果与约束冲突异常

Posted

技术标签:

【中文标题】Hibernate JPA双向一对多结果与约束冲突异常【英文标题】:Hibernate JPA bidirectional one-to-many results with constraint violation exception 【发布时间】:2020-12-28 17:39:23 【问题描述】:

我开始学习hibernate JPA,并尝试创建双向一对多关系,但由于某种原因导致org.hibernate.exception.ConstraintViolationException: could not execute statement

假设我有一个实体卡和实体甲板。每副牌可以有多张牌,但每张牌只能属于一副牌。我是这样弄的:

这是卡片实体:

/**
 * Represents a card in deck.
 *
 * @author wintermute
 */
@Data
@Entity(name = "card")
@Table(name = "card")
@NamedQueries( @NamedQuery(name = "Card.getAll", query = "SELECT c FROM card c WHERE c.containedInDeck = :deck_id"),
                @NamedQuery(name = "Card.remove", query = "DELETE FROM card c WHERE c.id = :id"))
public class Card

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;
    private String containedText;

    @ManyToOne
    @JoinColumn(name = "deck_id")
    private Deck containedInDeck;

这是套牌:

/**
 * Represents card deck containing cards sorted by deck's type.
 *
 * @author wintermute
 */
@Data
@Entity
@Table(name = "deck")
public class Deck

    @Id
    @GeneratedValue
    private long id;
    @Column(name = "type")
    private String typeOfDeck;

    @OneToMany(mappedBy = "containedInDeck")
    @ElementCollection(targetClass = Card.class)
    private Set<Card> containedCards = new HashSet<>();

现在这是我想要保存卡片实体的存储库:

    ...
    /**
     * @param card to persist in database.
     * @return true if operation was successful, false if operation failed.
     */
    public long add(Card card)
    
        try
        
            entityManager.getTransaction().begin();
            entityManager.persist(card);
            entityManager.flush();
            entityManager.getTransaction().commit();
            return card.getId();
         catch (IllegalStateException | PersistenceException e)
        
            log.error("Could not save entity: " + card + ", message: " + e.getMessage());
            return -1L;
        
    
    ...

在执行entityManager.flush() 时,由于违反约束而崩溃。我无法想象为什么。

【问题讨论】:

【参考方案1】:

因为Card#deck 引用的Deck 是非托管的,并且/或者它的id 不存在。如果要将Deck与卡一起保存,则需要在Card#deck上配置PERSIST级联。

【讨论】:

以上是关于Hibernate JPA双向一对多结果与约束冲突异常的主要内容,如果未能解决你的问题,请参考以下文章

JPA+Hibernate - 实体关系中的循环 - 级联策略

Hibernate 双向多对多拆分成两个一对多

使用 H2、JPA 注释和 Hibernate 问题的一对多关联

Hibernate双向一对多映射关系

spring Data jpa 一对多关联 动态查询怎么写

JPA 一对多双向堆栈溢出问题