使用Hibernate保存对象时收到以下错误
object references an unsaved transient instance - save the transient instance before flushing
使用Hibernate保存对象时收到以下错误
object references an unsaved transient instance - save the transient instance before flushing
当前回答
我在持久化一个实体时遇到了这种情况,在该实体中,数据库中的现有记录对于用@Version注释的字段具有NULL值(用于乐观锁定)。将数据库中的NULL值更新为0已更正此问题。
其他回答
介绍
使用JPA和Hibernate时,实体可以处于以下4种状态之一:
新建-新创建的对象从未与Hibernate会话(也称为持久性上下文)关联,且未映射到任何数据库表行,则被视为处于新建或临时状态。
为了持久化,我们需要显式调用持久化方法或使用传递持久化机制。
持久性-持久性实体已与数据库表行关联,并由当前运行的持久性上下文管理。
对此类实体所做的任何更改都将被检测并传播到数据库(在会话刷新时间内)。
分离-一旦当前运行的Persistence Context关闭,所有以前管理的实体都将分离。将不再跟踪连续的更改,并且不会发生自动数据库同步。移除-虽然JPA要求只允许移除托管实体,但Hibernate也可以删除分离的实体(但只能通过移除方法调用)。
实体状态转换
要将实体从一个状态移动到另一个状态,可以使用persistent、remove或merge方法。
解决问题
您在问题中描述的问题:
object references an unsaved transient instance - save the transient instance before flushing
是通过将状态为“新建”的实体与状态为“托管”的实体关联而导致的。
当您将子实体关联到父实体中的一对多集合,并且集合不级联实体状态转换时,可能会发生这种情况。
因此,您可以通过向触发此故障的实体关联添加级联来解决此问题,如下所示:
@OneToOne协会
@OneToOne(
mappedBy = "post",
orphanRemoval = true,
cascade = CascadeType.ALL)
private PostDetails details;
请注意我们为级联属性添加的CascadeType.ALL值。
@OneToMany协会
@OneToMany(
mappedBy = "post",
orphanRemoval = true,
cascade = CascadeType.ALL)
private List<Comment> comments = new ArrayList<>();
同样,CascadeType.ALL适用于双向@OneToMany关联。
现在,为了使级联在双向中正常工作,还需要确保父关联和子关联同步。
@ManyToMany协会
@ManyToMany(
mappedBy = "authors",
cascade = {
CascadeType.PERSIST,
CascadeType.MERGE
}
)
private List<Book> books = new ArrayList<>();
在@ManyToMany关联中,不能使用CascadeType.ALL或orphanRemove,因为这会将删除实体状态转换从一个父实体传播到另一个父图元。
因此,对于@ManyToMany关联,通常级联CascadeType.PERSIST或CascadeType.MERGE操作。或者,可以将其扩展到DETACH或REFRESH。
如果您的集合可以为null,请尝试:object.SetYouColaction(null);
在我的例子中,当我试图使用对具有空id的实体的引用来检索相关实体时,发生了这种情况。
@Entity
public class User {
@Id
private Long id;
}
@Entity
public class Address {
@Id
private Long id;
@JoinColumn(name="user_id")
@OneToOne
private User user;
}
interface AddressRepository extends JpaRepository<Address, Long> {
Address findByUser(User user);
}
User user = new User(); // this is transient, does not have id populated
// user.setId(1L) // works fine if this is uncommented
addressRepository.findByUser(user); // throws exception
我认为这是因为您试图持久化一个对象,该对象具有对另一个尚未持久化的对象的引用,因此它尝试在“DB端”放置对不存在的行的引用
除了所有其他好的答案之外,如果您使用merge来持久化一个对象,并且意外地忘记在父类中使用该对象的合并引用,那么可能会发生这种情况。考虑以下示例
merge(A);
B.setA(A);
persist(B);
在这种情况下,您合并了A,但忘记了使用A的合并对象。为了解决这个问题,您必须像这样重写代码。
A=merge(A);//difference is here
B.setA(A);
persist(B);