java 双向一对一中的“对象引用未保存的瞬态实例”
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/28386709/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
"object references an unsaved transient instance" in bidirectional one-to-one
提问by Ori Popowski
I have a simple one-to-one relation:
我有一个简单的一对一关系:
- Separate DAO for each entity.
- Transactions are managed by Spring.
- 为每个实体单独的 DAO。
- 事务由 Spring 管理。
PersonDao personDao = ctx.getBean(PersonDao.class, "personDaoImpl");
VehicleDao vehicleDao = ctx.getBean(VehicleDao.class, "vehicleDaoImpl");
Vehicle vehicle = new Vehicle("Audi");
Person person = new Person("Mike");
vehicle.setPerson(person);
person.setVehicle(vehicle);
personDao.save(person);
vehicleDao.save(vehicle);
Whenever I run the application I get the following exception:
每当我运行应用程序时,都会出现以下异常:
Exception in thread "main" org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.TransientPropertyValueException: object references an unsaved mike.Person.vehicle -> mike.Vehicle; nested exception is java.lang.IllegalStateException: org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing : mike.Person.vehicle -> mike.Vehicle
I tried saving the entities in both orders:
我尝试以两个顺序保存实体:
personDao.save(person);
vehicleDao.save(vehicle);
and
和
vehicleDao.save(vehicle);
personDao.save(person);
and I get the same exception.
我得到了同样的例外。
I was able to solve this by:
我能够通过以下方式解决这个问题:
- Using cascading.
- I guess that OpenSessionInView would also work.
- 使用级联。
- 我猜 OpenSessionInView 也可以工作。
The question is if are there any better solutions? Maybe I'm doing something fundamentally wrong?
问题是是否有更好的解决方案?也许我在做一些根本错误的事情?
Here are the (trivial) entities and DAOs:
以下是(琐碎的)实体和 DAO:
@Entity
public class Person {
@Id @GeneratedValue
private int id;
private String name;
@OneToOne
private Vehicle vehicle;
/* getters, setters, constructors */
}
--
——
@Entity
public class Vehicle {
@Id @GeneratedValue
private int id;
private String name;
@OneToOne
private Person person;
/* getters, setters, constructors */
}
--
——
@Repository
public class PersonDaoImpl implements PersonDao {
@PersistenceContext
private EntityManager em;
@Transactional
public void save(Person p) {
em.persist(p);
}
}
--
——
@Repository
public class VehicleDaoImpl implements VehicleDao {
@PersistenceContext
private EntityManager em;
@Transactional
public void save(Vehicle v) {
em.persist(v);
}
}
采纳答案by duckstep
You can use cascading or persist both entities in a single transaction:
您可以在单个事务中使用级联或保留两个实体:
@Transactional
void savePersonVehiclePair(Person person, Vehicle vehicle){
personDao.save(person);
vehicleDao.save(vehicle);
}
回答by The Coder
I got this error, it was a big headache until I figured out why.. Like it's saying
我遇到了这个错误,这让我很头疼,直到我弄清楚原因......就像它说的
object references an unsaved transient instance // Read it again
Actual reason, your object - here foreign key mapping object is refering to a value which not available (not available in the table at time of doing dao operation) in the primary key field of the table which holds the primary key. So you've to perform operation on primary key table before performing operation on model class which holds the foreign key..
实际原因,您的对象 - 这里的外键映射对象指的是在包含主键的表的主键字段中不可用(在执行 dao 操作时在表中不可用)的值。因此,您必须在对保存外键的模型类执行操作之前对主键表执行操作。
If you get confused by above paragraph, then I'll make it short and sweet
如果你对上面的段落感到困惑,那么我会让它简短而甜蜜
Your foreign key is referring a value which is not available in the primary key field
您的外键引用的值在主键字段中不可用
Try sysout
the foreign key's value by
尝试sysout
外键的值
System.out.println(modelClassObject.getForeignKeyGetter().getId());
I'm sure it'll return either 0 or a value which is not available in the primary key field which the foreign key is referring.
我确定它会返回 0 或在外键所指的主键字段中不可用的值。
回答by Domkat B Stephen
well, i just faced the same issue and so want to share how i went about the exception. After patiently going through my jsp, I realized i made a careless mistake: instead of setting the path attribute to "bioData.address.lga.lgaId" as shown in the code snippet below, i had carelessly set it to "bioData.address.lga.lgaName". so the primary key which was the lgaId wasn't mapped to the lga object, so there was no way for the key to be mapped to the object.
好吧,我刚刚遇到了同样的问题,所以想分享我是如何处理异常的。在耐心地检查我的 jsp 之后,我意识到我犯了一个粗心的错误:我没有将路径属性设置为“bioData.address.lga.lgaId”,如下面的代码片段所示,而是粗心地将其设置为“bioData.address”。 lga.lgaName”。所以作为 lgaId 的主键没有映射到 lga 对象,所以没有办法将键映射到对象。
<form:select path="bioData.address.lga.lgaId" id="title" required="required" class="form-control col-md-7 col-xs-12">
<c:forEach items="${lgaList}" var="lga">
<form:option value="${lga.lgaId }"><c:out value="${lga.name}"/></form:option>
</c:forEach>
</form:select>
the code below was the wrong code:
下面的代码是错误的代码:
<form:select path="bioData.address.lga.lgaName" id="title" required="required" class="form-control col-md-7 col-xs-12">
<c:forEach items="${lgaList}" var="lga">
<form:option value="${lga.lgaId }"><c:out value="${lga.name}"/></form:option>
</c:forEach>
</form:select>
it is now working fine.
它现在工作正常。