Hibernate级联持久化

8

我有一个关于Hibernate的一般性问题,正为此苦苦挣扎。

我有A类和B类,其中B类依赖于A。

在我的代码中,当我调用em.persist(objOfTypeA)时,我希望插入会同时插入到AAA表和BBB表。如果我手动保存A获取A的ID并将其填入每个对象的列表中,然后保存该列表,事情就能够运行。

但我希望这一切可以被Hibernate神奇地处理。

我是做错了什么吗? 还是我对Hibernate的期望值过高?

谢谢

@Entity
@Table(name = "AAA")
@Veto
public class A {

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


    @NotNull
    @Column(name = "Name")
    private Long name;

    ...

    @OneToMany(mappedBy="a", fetch=FetchType.LAZY, cascade={CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE})
    private List<B> b;
...
}

@Entity
@Table(name = "BBB")
@Veto
public class B {

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

    @NotNull
    @Column(name="AId")
    private Long aId;

    @NotNull
    @Column(name = "Name")
    private Long name;

    @JoinColumn(name = "AId", referencedColumnName="Id", updatable = false, insertable = false)
    @ManyToOne(optional = false)
    private A a;
...     
}
2个回答

3

我终于解决了这个问题。 我所得到的或者找到的所有示例都没有告诉我到底哪里出了问题,只有通过自己的实验才得出了这个结论:

与其使用

@OneToMany(mappedBy="a", fetch=FetchType.LAZY, cascade={CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE})
private List<B> b;

这个没有起作用(FK仍然为NULL)

这个起作用了:

@OneToMany(fetch=FetchType.LAZY, cascade={CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE})
@JoinColumn(name="AId")
@NotNull
private List<B> b;

这对我不起作用。问题是Hibernate希望在持久化之前先在B上设置A。这个方法有效:https://dev59.com/U3I-5IYBdhLWcg3wj5FG - user41871

1

将类B的映射修改如下:

@Entity
@Table(name = "BBB")
@Veto
public class B {

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

    @NotNull
    @Column(name="AId", updatable = false, insertable = false)
    private Long aId;

    @NotNull
    @Column(name = "Name")
    private Long name;

    @JoinColumn(name = "AId", referencedColumnName="Id")
    @ManyToOne(optional = false)
    private A a;
...     
}

你在错误的位置使用了属性updatable = false, insertable = false,我已经进行了更正。
阅读这里以了解它们的作用。

嗨ManuPK,感谢您的回答,但这并没有解决我的问题。在尝试持久化(A)时,我遇到了一个错误,即B的aId为空。ConstraintViolationImpl {interpolatedMessage ='may not be null',propertyPath = aId,rootBeanClass = class com.test.model.B,messageTemplate =' {javax.validation.constraints.NotNull.message}'}我不确定在SQL Server端是否需要将两个id(A和B的)都作为标识,还是Hibernate会处理它?但我假设这没问题,因为它没有抱怨那个,而是在FK上抱怨。 - WonkeyDonkey
数据库看起来是这样的: 表1:AAA Id bigint 非空, Name varchar(100)表2:BBB Id bigint 非空, AId bigint 非空, Name varchar(100)谢谢! - WonkeyDonkey
我回到数据库中,从AId中删除了“not null”,并且还从B类中的aId中删除了@NotNull。现在持久化成功了,但是当我查看数据库时,AAA一切正常,但BBB缺少AId。 求助。。 - WonkeyDonkey
按照这个示例创建类。 - ManuPK

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接