"object references an unsaved transient instance" 双向一对一
"object references an unsaved transient instance" in bidirectional one-to-one
我有一个简单的一对一关系:
- 每个实体的单独 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);
每当我 运行 应用程序时,我都会收到以下异常:
线程异常 "main"
org.springframework.dao.InvalidDataAccessApiUsageException:
org.hibernate.TransientPropertyValueException: 对象引用了一个未保存的
mike.Person.vehicle -> mike.Vehicle;嵌套异常是
java.lang.IllegalStateException: org.hibernate.TransientPropertyValueException:
对象引用未保存的瞬态实例 - 保存瞬态实例
冲洗前:mike.Person.vehicle -> mike.Vehicle
我尝试按两个顺序保存实体:
personDao.save(person);
vehicleDao.save(vehicle);
和
vehicleDao.save(vehicle);
personDao.save(person);
我也遇到了同样的异常。
我通过以下方式解决了这个问题:
- 使用级联。
- 我想 OpenSessionInView 也可以。
请问有没有更好的解决办法?也许我在做一些根本性的错误?
以下是(琐碎的)实体和 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);
}
}
我收到了这个错误,这让我很头疼,直到我弄清楚原因..就像它说的
object references an unsaved transient instance // Read it again
实际原因,你的对象 - 这里的外键映射对象指的是 table 保存主键。因此,在对包含外键的模型 class 执行操作之前,您必须对主键 table 执行操作..
如果你对上面的段落感到困惑,那么我会把它写得简短而亲切
您的外键引用的值在主键字段中不可用
通过
尝试sysout
外键的值
System.out.println(modelClassObject.getForeignKeyGetter().getId());
我确定它会 return 0 或在外键引用的主键字段中不可用的值。
您可以在单个事务中使用级联或保留两个实体:
@Transactional
void savePersonVehiclePair(Person person, Vehicle vehicle){
personDao.save(person);
vehicleDao.save(vehicle);
}
好吧,我刚遇到同样的问题,所以想分享一下我是如何处理异常的。在耐心地检查了我的 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>
下面的代码是错误的代码:
<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>
现在工作正常。
我有一个简单的一对一关系:
- 每个实体的单独 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);
每当我 运行 应用程序时,我都会收到以下异常:
线程异常 "main" org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.TransientPropertyValueException: 对象引用了一个未保存的 mike.Person.vehicle -> mike.Vehicle;嵌套异常是 java.lang.IllegalStateException: org.hibernate.TransientPropertyValueException: 对象引用未保存的瞬态实例 - 保存瞬态实例 冲洗前:mike.Person.vehicle -> mike.Vehicle
我尝试按两个顺序保存实体:
personDao.save(person);
vehicleDao.save(vehicle);
和
vehicleDao.save(vehicle);
personDao.save(person);
我也遇到了同样的异常。
我通过以下方式解决了这个问题:
- 使用级联。
- 我想 OpenSessionInView 也可以。
请问有没有更好的解决办法?也许我在做一些根本性的错误?
以下是(琐碎的)实体和 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);
}
}
我收到了这个错误,这让我很头疼,直到我弄清楚原因..就像它说的
object references an unsaved transient instance // Read it again
实际原因,你的对象 - 这里的外键映射对象指的是 table 保存主键。因此,在对包含外键的模型 class 执行操作之前,您必须对主键 table 执行操作..
如果你对上面的段落感到困惑,那么我会把它写得简短而亲切
您的外键引用的值在主键字段中不可用
通过
尝试sysout
外键的值
System.out.println(modelClassObject.getForeignKeyGetter().getId());
我确定它会 return 0 或在外键引用的主键字段中不可用的值。
您可以在单个事务中使用级联或保留两个实体:
@Transactional
void savePersonVehiclePair(Person person, Vehicle vehicle){
personDao.save(person);
vehicleDao.save(vehicle);
}
好吧,我刚遇到同样的问题,所以想分享一下我是如何处理异常的。在耐心地检查了我的 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>
下面的代码是错误的代码:
<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>
现在工作正常。