Reputation: 10672
I have a simple one-to-one relation:
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:
The question is if are there any better solutions? Maybe I'm doing something fundamentally wrong?
Here are the (trivial) entities and DAOs:
@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);
}
}
Upvotes: 4
Views: 23689
Reputation: 21
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.
<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.
Upvotes: 0
Reputation: 2632
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..
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
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.
Upvotes: 4
Reputation: 1138
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);
}
Upvotes: 3