Tus*_*rao 546 java orm hibernate
使用Hibernate保存对象时收到以下错误
object references an unsaved transient instance - save the transient instance before flushing
Run Code Online (Sandbox Code Playgroud)
Boz*_*zho 727
您应该在集合映射中包含cascade="all"
(如果使用xml)或cascade=CascadeType.ALL
(如果使用注释).
发生这种情况是因为您的实体中有一个集合,并且该集合具有一个或多个数据库中不存在的项目.通过指定上述选项,您可以告诉hibernate在保存父项时将它们保存到数据库中.
小智 225
我相信这可能只是重复回答,但只是为了澄清,我在@OneToOne
映射和a 上得到了这个@OneToMany
.在这两种情况下,事实是Child
我添加到的对象Parent
尚未保存在数据库中.因此,当我添加Child
到Parent
,然后保存Parent
,Hibernate会"object references an unsaved transient instance - save the transient instance before flushing"
在保存Parent时抛出消息.
在两个案例中添加了cascade = {CascadeType.ALL}
对Parent's
引用的Child
解决问题.这节省了Child
和Parent
.
对不起,任何重复的答案,只是想进一步澄清人们.
@OneToOne(cascade = {CascadeType.ALL})
@JoinColumn(name = "performancelog_id")
public PerformanceLog getPerformanceLog() {
return performanceLog;
}
Run Code Online (Sandbox Code Playgroud)
Vla*_*cea 88
使用 JPA 和 Hibernate 时,实体可以处于以下 4 种状态之一:
要成为持久化,我们需要显式调用该persist
方法或利用传递持久化机制。
将检测到对此类实体所做的任何更改并将其传播到数据库(在会话刷新时间期间)。
分离- 一旦当前运行的持久性上下文关闭,所有以前管理的实体都将分离。将不再跟踪后续更改,也不会发生自动数据库同步。
Removed - 尽管 JPA 要求只允许删除托管实体,但 Hibernate 也可以删除分离的实体(但只能通过remove
方法调用)。
要将实体从一种状态移动到另一种状态,您可以使用persist
,remove
或merge
方法。
您在问题中描述的问题:
object references an unsaved transient instance - save the transient instance before flushing
Run Code Online (Sandbox Code Playgroud)
是由于将处于New状态的实体与处于Managed状态的实体相关联引起的 。
当您将子实体与父实体中的一对多集合相关联,并且该集合没有cascade
实体状态转换时,就会发生这种情况。
因此,您可以通过向触发此故障的实体关联添加级联来解决此问题,如下所示:
@OneToOne
协会@OneToOne(
mappedBy = "post",
orphanRemoval = true,
cascade = CascadeType.ALL)
private PostDetails details;
Run Code Online (Sandbox Code Playgroud)
注意
CascadeType.ALL
我们为cascade
属性添加的值。
@OneToMany
协会@OneToMany(
mappedBy = "post",
orphanRemoval = true,
cascade = CascadeType.ALL)
private List<Comment> comments = new ArrayList<>();
Run Code Online (Sandbox Code Playgroud)
同样,CascadeType.ALL
适用于双向@OneToMany
关联。
现在,为了让级联在双向中正常工作,您还需要确保父子关联是同步的。
@ManyToMany
协会@ManyToMany(
mappedBy = "authors",
cascade = {
CascadeType.PERSIST,
CascadeType.MERGE
}
)
private List<Book> books = new ArrayList<>();
Run Code Online (Sandbox Code Playgroud)
在@ManyToMany
关联中,您不能使用CascadeType.ALL
ororphanRemoval
因为这会将删除实体状态转换从一个父实体传播到另一个父实体。
因此,对于@ManyToMany
关联,您通常会级联CascadeType.PERSIST
或CascadeType.MERGE
操作。或者,您可以将其扩展为DETACH
或REFRESH
。
Coo*_*ino 59
当Hibernate认为需要保存与您正在保存的对象关联的对象时保存对象时会发生这种情况.
我有这个问题,并且不想保存对引用对象的更改,所以我希望级联类型为NONE.
诀窍是确保引用对象中的ID和VERSION设置为Hibernate不认为引用的对象是需要保存的新对象.这对我有用.
查看要保存的类中的所有关系,以计算关联对象(以及关联对象的关联对象),并确保在对象树的所有对象中设置ID和VERSION.
Har*_*gić 28
或者,如果你想使用最小的"权力"(例如,如果你不想要级联删除)来实现你想要的,使用
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
...
@Cascade({CascadeType.SAVE_UPDATE})
private Set<Child> children;
Run Code Online (Sandbox Code Playgroud)
all*_*lap 22
在我的情况下,它是由尚未造成CascadeType
的@ManyToOne
双向关系的一面.更确切地说,我CascadeType.ALL
站在@OneToMany
一边并且没有使用它@ManyToOne
.添加CascadeType.ALL
到@ManyToOne
解决了这个问题.
一对多方面:
@OneToMany(cascade = CascadeType.ALL, mappedBy="globalConfig", orphanRemoval = true)
private Set<GlobalConfigScope>gcScopeSet;
Run Code Online (Sandbox Code Playgroud)
多对一方(导致问题)
@ManyToOne
@JoinColumn(name="global_config_id")
private GlobalConfig globalConfig;
Run Code Online (Sandbox Code Playgroud)
多对一(通过添加固定CascadeType.PERSIST
)
@ManyToOne(cascade = CascadeType.PERSIST)
@JoinColumn(name="global_config_id")
private GlobalConfig globalConfig;
Run Code Online (Sandbox Code Playgroud)
nan*_*eck 10
这不是错误的唯一原因.我刚刚遇到它,因为我的编码中出现了拼写错误,我相信,它设置了一个已经保存的实体的值.
X x2 = new X();
x.setXid(memberid); // Error happened here - x was a previous global entity I created earlier
Y.setX(x2);
Run Code Online (Sandbox Code Playgroud)
我通过找到导致错误的确切变量(在这种情况下String xid
)来发现错误.我使用了catch
整个代码块来保存实体并打印出跟踪.
{
code block that performed the operation
} catch (Exception e) {
e.printStackTrace(); // put a break-point here and inspect the 'e'
return ERROR;
}
Run Code Online (Sandbox Code Playgroud)
小智 8
当您具有 OneToMany 关系并且尝试将子实体添加到父实体中的列表,然后通过父实体检索此列表(在保存此父实体之前),而不保存子实体本身时,也可能会发生这种情况,例如:
Child childEntity = new Child();
parentEntity.addChild(childEntity);
parentEntity.getChildren(); // I needed the retrieval for logging, but one may need it for other reasons.
parentRepository.save(parentEntity);
Run Code Online (Sandbox Code Playgroud)
当我保存父实体时抛出错误。如果我删除了上一行中的检索,则不会引发错误,但这当然不是解决方案。
解决方案是保存 childEntity 并将保存的子实体添加到父实体,如下所示:
Child childEntity = new Child();
Child savedChildEntity = childRepository.save(childEntity);
parentEntity.addChild(savedChildEntity);
parentEntity.getChildren();
parentRepository.save(parentEntity);
Run Code Online (Sandbox Code Playgroud)
在Cascade.All
你真的必须这样做之前不要使用.Role
并且Permission
具有双向manyToMany
关系.然后以下代码将正常工作
Permission p = new Permission();
p.setName("help");
Permission p2 = new Permission();
p2.setName("self_info");
p = (Permission)crudRepository.save(p); // returned p has id filled in.
p2 = (Permission)crudRepository.save(p2); // so does p2.
Role role = new Role();
role.setAvailable(true);
role.setDescription("a test role");
role.setRole("admin");
List<Permission> pList = new ArrayList<Permission>();
pList.add(p);
pList.add(p2);
role.setPermissions(pList);
crudRepository.save(role);
Run Code Online (Sandbox Code Playgroud)
而如果对象只是一个"新"对象,那么它会抛出相同的错误.
当我在标记为 的方法中创建新实体和关联实体@Transactional
,然后在保存之前执行查询时,我遇到了这个问题。前任
@Transactional
public someService() {
Entity someEntity = new Entity();
AssocaiatedEntity associatedEntity = new AssocaitedEntity();
someEntity.setAssociatedEntity(associatedEntity);
associatedEntity.setEntity(someEntity);
// Performing any query was causing hibernate to attempt to persist the new entity. It would then throw an exception
someDao.getSomething();
entityDao.create(someEntity);
}
Run Code Online (Sandbox Code Playgroud)
为了解决这个问题,我在创建新实体之前执行了查询。
要加上我的2美分,当我不小心发送null
ID 时也遇到了同样的问题。下面的代码描述了我的情况(OP没有提及任何特定情况)。
Employee emp = new Employee();
emp.setDept(new Dept(deptId)); // --> when deptId PKID is null, same error will be thrown
// calls to other setters...
em.persist(emp);
Run Code Online (Sandbox Code Playgroud)
在这里,我将现有部门ID设置为新的员工实例,而实际上并没有首先获取部门实体,因为我不想触发另一个选择查询。
在某些情况下,deptId
PKID null
来自调用方法,并且出现相同的错误。
因此,请注意null
PK ID的值
除了所有其他好的答案之外,如果您merge
用来持久化对象并且不小心忘记在父类中使用对象的合并引用,则可能会发生这种情况。考虑下面的例子
merge(A);
B.setA(A);
persist(B);
Run Code Online (Sandbox Code Playgroud)
在这种情况下,您合并A
但忘记使用A
. 要解决这个问题,你必须像这样重写代码。
A=merge(A);//difference is here
B.setA(A);
persist(B);
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
546950 次 |
最近记录: |